DT - DateTime wrapper that tries hard to DWYM
use DT; my $dt_now = DT->new(time); # Just works my $dt_past = DT->new('2018-02-06T15:45:00-0500'); # Just works my ($pg_time_str) = $pg_dbh->selectrow_array("SELECT now();") my $dt_pg = DT->new($pg_time_str); # Also just works say "Wowza!" if $dt_now < time + 1; # Unexpectedly, works too! say "$dt_now"; # 2018-07-27T03:49:49Z use DateTime::Format::Pg; say $dt_now->pg_timestamp_notz; # 2018-07-27 03:49:49 say $dt_now->pg_timestamp_tz; # 2018-07-27 03:49:49+0000
DT is a very simple and thin wrapper over DateTime::Moonpig, which in turn is a wrapper over DateTime. DateTime::Moonpig brings immutability and saner operator overloading at the cost of a cartoonish name but also lacks date/time parsing capabilities that are badly needed all the time.
There is a myriad of helpful modules on CPAN but oh all that typing!
Consider:
use DateTime; my $dt = DateTime->from_epoch(epoch => time); use DateTime::Format::Pg; my $dt = DateTime::Format::Pg->parse_datetime($timestamp_from_postgres); my $date_str = DateTime::Format::Pg->format_timestamp_without_time_tzone($dt); use DateTime::Format::ISO8601; use DateTime::Format::ISO8601::Format; my $dt = DateTime::Format::ISO8601->parse_datetime($iso_datetime); my $date_str = DateTime::Format::ISO8601::Format->new->format_datetime($dt);
Versus:
use DT ':pg'; my $dt_unix = DT->new(time); my $dt_pg = DT->new($timestamp_from_postgres); my $dt_iso = DT->new($iso_datetime); my $date_str = "$dt_unix";
DT constructor will try to Do What You Mean, and if it cannot it will fall back to default DateTime constructor. Simple.
One thing that DateTime::Moonpig authors get right is data immutability: any operations on a DateTime object should not mutate original object as this leads to a multitude of potential prioblems.
However the solution presented in DateTime::Moonpig is to throw an exception when a mutator method is called, which is far from Doing What I Mean. Even more, with add_duration and subtract_duration methods rendered effectively unusable the only way to handle date arithmetic suggested is by adding or subtracting the number of seconds from the date which semantically is not the same as adding or subtracting days/months/etc.
add_duration
subtract_duration
A more reasonable approach is to clone the date object, perform the mutation on the copy and return the new object.
Yet another pretty annoying DateTime quirk is comparison operator overloading. In my humble opinion it is not very unreasonable to expect a sophisticated date module to automatically grok something like this and Just Work without throwing an exception, or requiring a metric ton of boilerplate:
if ( $dt < time ) { ... }
As a side effect of added operator overload DT also has saner semantics for comparing with undef values: the result of course is undef.
DT
undef
The following mutator methods are overridden to return a new DT object instead of performing operations on the original object:
add, add_duration, subtract, subtract_duration, truncate, set, set_time_zone, set_year, set_month, set_day, set_hour, set_minute, set_second, set_nanosecond
add
subtract
truncate
set
set_time_zone
set_year
set_month
set_day
set_hour
set_minute
set_second
set_nanosecond
Note that set_locale and set_formatter are not overridden. These methods do not affect the actual date/time value so are safe to use.
set_locale
set_formatter
DT also adds a few useful methods:
unix_time
A synonym for epoch. No special magic, just easier to remember.
epoch
pg_timestamp_notz
Format $dt object into a string suitable for PostgreSQL TIMESTAMP WITHOUT TIME ZONE type column.
TIMESTAMP WITHOUT TIME ZONE
pg_timestamp_tz
Format $dt object into a string suitable for PostgreSQL TIMESTAMP WITH TIME ZONE type column.
TIMESTAMP WITH TIME ZONE
To install this module type the following:
perl Makefile.PL make && make test && make install
DateTime::Moonpig is the parent class for DT. DateTime::Format::ISO8601 is required for parsing ISO8601 date/time formats, and DateTime::Format::ISO8601::Format is required for stringification.
PostgreSQL related methods are optional and depend on DateTime::Format::Pg being installed.
No doubt there are some. Please post an issue on GitHub (see below) if you find something. Pull requests are also welcome.
GitHub repository: https://github.com/nohuhu/DT
Copyright (c) 2018 by Alex Tokarev <nohuhu@cpan.org>.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See "perlartistic".
To install DT, copy and paste the appropriate command in to your terminal.
cpanm
cpanm DT
CPAN shell
perl -MCPAN -e shell install DT
For more information on module installation, please visit the detailed CPAN module installation guide.