Date - extremely fast Date framework with timezones, microseconds, relative dates and intervals support.
SYNOPSIS
use Date qw/date date_ymd rdate rdate_ymd tzset/;
my $date = Date->new($epoch); # using server's local timezone
$date = Date->new("2013-03-05 23:45:56.345");
$date = Date->new_ymd($y,$m,$d,$h,$m,$s);
$date = Date->new_ymd(year => $y, month => $m, day => $d, hour => $h, min => $m, sec => $s, mksec => $mks);
$date = Date::now(); # same as Date->new(time()) but faster
$date = Date::today(); # same as Date->new(time())->truncate but faster
$date = Date::now_hires(); # current time with microseconds
# create using function 'date'
tzset('Europe/Moscow'); # using 'Europe/Moscow' as server's local timezone
$date = date(123456789);
$date = date("2001/11/12 07:13:12", 'America/New_York'); # $date operates in custom time zone
# creating relative date object
# (normally you don't need to create this object explicitly)
$reldate = Date::Rel->new("3Y 1M 3D 6h 2m 4s");
$reldate = Date::Rel->new("6Y");
$reldate = Date::Rel->new($secs);
$reldate = Date::Rel->new_ymd($year,$month,$day,$hour,$min,$sec);
$reldate = Date::Rel->new_ymd(year => $year, month => $month, day => $day, hour => $hour, min => $min, sec => $sec);
$reldate = rdate "-1M -3D 6h";
$reldate = 3*MONTH; # "3M"
$reldate = 2*YEAR + MONTH - 30*DAY; # "2Y 1M -30D"
print $reldate/2; # 1Y 5h 14m 32s
$reldate = YEAR/2 + HOUR/2; # 6M 30m
$date; # prints the date in default output format (ISO/SQL format)
$date->epoch; # unix timestamp
$date->year; # year, e.g: 2001
$date->c_year; # year - 1900, e.g. 101
$date->yr; # 2-digit year 0-99, e.g 1
$date->month; # month 1..12
$date->mon; # same as prev.
$date->c_month; # month 0..11
$date->day; # day of month
$date->mday; # day of month
$date->day_of_month;# same as prev.
$date->hour;
$date->min;
$date->minute; # same as prev.
$date->sec;
$date->second; # same as prev.
$date->mksec;
$date->wday; # 1-7, Sunday-Saturday
$date->day_of_week; # same as prev.
$date->c_wday; # 0-6, Sunday-Saturday
$date->ewday; # 1-7, Monday-Sunday
$date->yday; # day of year [1-366]
$date->day_of_year; # same as prev.
$date->c_yday; # [0-365]
$date->isdst; # DST?
$date->daylight_savings; # same as prev.
$date->strftime($format);
$date->month_name; # March
$date->month_sname; # Mar
$date->wday_name; # Thursday
$date->wday_sname; # Thu
$date->to_string # 2000-02-29 12:21:11
"$date" # same as prev.
$date->to_string(Date::FORMAT_ISO8601); # 2000-02-29T12:21:11+03:00
$date->gmtoff # current offset from UTC (in seconds)
$date->tzname # returns the timezone name (EST, EET, etc)
$date->tzlocal # true if $date is in local time zone
$date->timezone # returns timezone object
$date->timezone('GMT+5') # changes $date's timezone (saving YMDhms)
$date->to_timezone('UTC') # changes $date's timezone (saving epoch)
($year,$month,$day,$hour,$min,$sec) = $date->array;
($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = $date->struct;
# constructing new date based on an existing one:
$new_date = $date->clone;
$new_date = $date->clone(year => 1977, sec => 14, tz => 'Australia/Melbourne');
# valid keys: year, month, day, hour, min, sec, tz
$date->month_begin # First day of the month (date object)
$date->month_end # Last day of the month
$date->days_in_month # 28..31
# error handling
$a = date($date_string);
if ($a) { # valid date
...
} else { # invalid date
if ($a->error == Date::Error::parser_error) { ... }
print $a->error->message;
}
# date range check
Date::range_check(0); # this is the default
print date("2001-02-31"); # will print 2001-03-03
Date::range_check(1);
print date("2001-02-31"); # will print nothing
# getting values of a relative date object
$reldate->year;
$reldate->month;
$reldate->day;
$reldate->hour;
$reldate->min;
$reldate->sec;
"$reldate"; # reldate in "1Y 2M 3D 4h 5m 6s" format
$reldate->duration; # duration in seconds
int $reldate; # same as prev
$reldate->to_secs; # same as prev
$reldate->to_mins; # relative date in minutes
$reldate->to_hours; # relative date in hours
$reldate->to_days; # relative date in days
$reldate->to_months; # relative date in months
$reldate->to_years; # relative date in years
# arithmetic with dates:
print date_ymd(2001,12,11,4,5,6)->truncate; # "2001-12-11"
$new_date = $date + $reldate;
$date2 = $date - '3Y 2D'; # 3 Years and 2 days
$date3 = $date + rdate_ymd(1,2,3); # $date plus 1 year, 2 months, 3 days
# accurate relative dates
$rel = $date1 - $date2;
$rel->duration; # accurate number of seconds in interval
$rel->to_months; # accurate number of months in interval
$rel->includes("2013-01-01") # returns -1, 0, or 1
$days_between = ($date1 - $date2)->to_days;
# comparison between absolute dates
print $date1 > $date2 ? "I am older" : "I am younger";
# comparison between relative dates
print $reldate1 > $reldate2 ? "I am faster" : "I am slower";
# Adding / Subtracting months and years are sometimes tricky:
print date("2001-01-29") + '1M' - '1M'; # gives "2001-02-01"
print date("2000-02-29") + '1Y' - '1Y'; # gives "2000-03-01"
#strict mode
{
use Date::strict;
my $d = Date->new("invalid date"); # throws
my $rel = Date::Rel->new("1X"); # throws
$d += "1X"; # throws
}
# like strptime(3)
$date4 = Date::strptime('2019-02-03 04:05:06 Europe/Moscow', '%Y-%m-%d %H:%M:%S %Z');
DESCRIPTION
Date is a port of C++ panda::date
framework which is complete feature-rich date framework, supporting timezones (not just offsets), microseconds, relative dates and intervals. Timezones with leap seconds (right/*) are also supported.
Date supports dates between -2147483648/01/01 00:00:00 and 2147483647/12/31 23:59:59 (on 64bit perls).
With Date you can perform some operations even faster than in plain C program using stdlibc functions because it has its own efficient low-level time functions implementation.
CLASS METHODS
new([$epoch = 0], [$timezone = local])
Creates date from UNIX timestamp (number of seconds since 1970). $epoch
may be non-integer value in which case microseconds is set.
new($string, [$timezone = local], [$format = INPUT_FORMAT_ALL])
Creates date from string in one of the following formats:
- Default iso date format
-
YYYY-MM-DD[ HH:MM[:SS[.ss]][±hh[:mm]|Z]] YYYY/MM/DD[ HH:MM[:SS[.ss]][±hh[:mm]|Z]] 2019-12-11 2019-12-11 14:56:23 2019-12-11 14:56:23.123 2019-12-11 14:56:23Z 2019/12/11 14:56+03:00 2019/12/11 14:56:23.123+03
.ss
is a microseconds part 1-6 digits long. - ISO 8601 most popular subset
-
YYYY-MM[-DD[THH[:MM[:SS[.ss]]][±hh[:mm]|Z]]]] YYYYMMDD[THH[MM[SS[.ss]]][±hh[mm]|Z]]] YYYY-Wnn[-n] 2019-12 2019-12-11T14:56:23 20191211T145623.123Z 20191211T145623.123+0300 2019-12-11T14:56:23.123-03:30 2019-W35 2019-W35-2
- RFC 822/1123
-
Tue, 10 Dec 2019 00:00:00 GMT 10 Dec 2019 00:00 Z
Only C locale supported.
- RFC 850
-
Tuesday, 01-Jan-19 03:04:00 GMT
Only C locale supported.
- ANSI C
-
Sun Sep 1 03:04:00 2019
Only C locale supported.
- Dotted format
-
DD.MM.YYYY
- Comman Log Format
-
dd/MMM/yyyy:hh:mm:ss +-hhmm [dd/MMM/yyyy:hh:mm:ss +-hhmm]
Only C locale supported.
If timezone offset designator is present inside string, the date is created in unnamed timezone with constant offset from GMT (no transition rules). $timezone
parameter is ignored in this case.
You can limit the number of allowed formats by passing $format
argument, which is the bitmask of the following constants: INPUT_FORMAT_ALL(the default), INPUT_FORMAT_ISO, INPUT_FORMAT_ISO8601, INPUT_FORMAT_RFC1123, INPUT_FORMAT_RFC850, INPUT_FORMAT_ANSI_C, INPUT_FORMAT_DOT, INPUT_FORMAT_CLF.
If $string
is an invalid date or a valid date but in format other than specified, then error()
is set to Date::Error::parser_error
.
If you want it to throw an exception on invalid inputs, see Date::strict.
new_ymd(%ymdhms)
Creates date from named YMDHMS arguments.
Date->new(
year => 2019
month => 12,
day => 31,
hour => 23,
min => 59,
sec => 59,
mksec => 123456,
tz => 'Europe/Moscow',
);
the default values for year is 1970, month&day - 1, others - 0, timezone - local.
If the date represented by YMDHMS is ambigious (falls into DST->STD timezone transition, i.e. when clock goes 1 hour back and certain HMS appears twice), the greater epoch is preferred. This behaviour can be altered with additional isdst
hash parameter. The default value is -1
(auto). 0
means 'prefer standart time', 1
means 'prefer daylight savings time'. If specified date is not ambigious, isdst
parameter is completely ignored.
new_ymd($year, [$month = 1], [$day = 1], [$hour = 0], [$min = 0], [$sec = 0], [$mksec = 0], [$timezone = local])
Created date from unnamed YMDHMS arguments.
new($date_object)
If $date_object
is a Date object, then returns copy of the date as clone()
. Otherwise stringifies $date_object
and create date as new($string)
. If this object does not have stringification overload, the result is date with parsing error.
new* [all variants]
Common behaviour for any of constructor variants.
If $timezone is present, created object will operate as if tzset($timezone)
was called, but without calling tzset()
.
If $timezone is absent (or undef or ""), local timezone will be used. Further changes of local timezone via tzset()
won't affect constructed object.
If there is any errors while creating an object, error()
will be set and the date is set to epoch=0. The object itself will return false in boolean context, empty string in string context and so on.
OBJECT METHODS
set(...)
set_ymd(%ymdhms | @ymdhms)
Set another date for object. This is faster than creating new object. See new()
and new_ymd()
for arguments details.
epoch([$epoch])
Get or set UNIX timestamp (integer or double with mksecs)
epoch_sec ()
Get UNIX timestamp as integer (without microseconds even if they are present).
year([$year])
Get or set year [-2**31, 2**31-1]
c_year([$year])
Get or set year counted from 1900 (C-style)
yr([$yr])
Get or set 2-digits-style-year [0-99]
month([$mon]), mon
Get or set month [1-12]
c_month([$mon])
Get or set month [0-11] (C-style)
day([$day]), mday, day_of_month
Get or set day of month [1-31]
hour([$hour])
Get or set hours [0-23]
min([$min]), minute
Get or set minutes [0-59]
sec([$sec]), second
Get or set seconds [0-60]
mksec([$mksec])
Get or set microseconds [0-999999]
wday([$wday]), day_of_week
Day of week. 1 = Sunday, ... , 7 = Saturday.
If you pass an argument then another day of the same week will be set.
c_wday([$wday])
C-style day of week. 0 = Sunday, ... , 6 = Saturday.
If you pass an argument then another day of the same week will be set.
ewday([$wday])
Europe-friendly day of week. 1 = Monday, ..., 7 = Sunday.
If you pass an argument then another day of the same week will be set.
yday([$yday]), day_of_year
Day of the year [1-366].
If you pass an argument then another day of the same year will be set.
c_yday([$yday])
C-style day of the year [0-365].
If you pass an argument then another day of the same year will be set.
isdst(), daylight_savings()
Is daylight savings time in effect now (true/false).
month_name()
Full name of the month
month_sname()
Short name of the month
wday_name()
Full name of the day
wday_sname()
Short name of the day
""
Same as to_string()
.
to_string($format = Date::FORMAT_ISO)
Stringifies date using $format
.
Available formats:
- Date::FORMAT_ISO
-
Default format
2019-12-31 23:59:59.123
Microseconds part will be absent if mksec == 0.
- Date::FORMAT_ISO_TZ
-
iso
with timezone offset2019-12-31 23:59:59.123+03:00
- Date::FORMAT_ISO_DATE
-
Only date
2019-12-31
- Date::FORMAT_ISO8601
-
2019-12-31T23:59:59.123+03:00
- Date::FORMAT_ISO8601_NOTZ
-
Same as
iso8601
but omits printing timezone offset2019-12-31T23:59:59.123
- Date::FORMAT_RFC1123
-
Tue, 10 Dec 2019 00:00:00 GMT
- Date::FORMAT_COOKIE
-
same as rfc1123
- Date::FORMAT_RFC850
-
Tuesday, 01-Jan-19 03:04:00 GMT
- Date::FORMAT_ANSI_C
-
Sun Sep 1 03:04:00 2019
- Date::FORMAT_YMD
-
2019/12/31
- Date::FORMAT_DOT
-
31.12.2019
- Date::FORMAT_HMS
-
23:59:59
- Date::FORMAT_CLF
-
10/Oct/1999:21:15:05 +0500
- Date::FORMAT_CLF_BRACKETS
-
[10/Oct/1999:21:15:05 +0500]
strftime($format)
Works like Date::strftime()
with current date's fields passed as arguments.
'bool', to_bool()
Called implicitly in boolean context
if ($date)
$date ? EXPR1 : EXPR2
$date && $something
Returns TRUE if date has no errors (i.e. has no parsing or out of range errors, etc), otherwise FALSE
'0+', to_number()
Returns epoch()
in numeric context
gmtoff()
Returns current timezone offset from UTC in seconds - may change when the date changes isdst/nodst.
tzname()
Returns the name of the object's timezone (Europe/Moscow, America/New_York, etc).
tzabbr()
Returns timezone abbreviation (EST, EET, etc) - may change when the date changes isdst/nodst.
tzlocal()
Returns TRUE if this object's timezone is set as local.
tz([$newzone])
With no arguments returns Date::Timezone object associated with the date.
With argument changes the timezone of current object to $newzone preserving YMDhms information (epoch may change) and returns nothing. $newzone
may be timezone object, name or rule.
to_tz($newzone)
Changes the timezone of current object to $newzone in a way that changed date still points to the same time moment (same epoch). YMDhms info may change. Returns nothing. $newzone
may be timezone object, name or rule.
array()
Returns elements list - $year,$month,$day,$hour,$min,$sec,[$mksec].
$year is year() [2013=2013]
$month is month() [1-12]
If $mksec == 0 it will not be on the list
struct()
Returns elements list - $sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst
$year is c_year() [113 = 2013]
$month is c_month() [0-11]
$wday is c_wday() [0-6]
$yday is c_yday() [0-365]
clone(%diff | @diff)
Returns copy of the date.
If you pass a hash-list or array then date is cloned with changes described in the hash/array.
Hash keys: year (YYYY), month [1-12], day, hour, min, sec, mksec, tz
Array: [$year (YYYY), $month [1-12], $day, $hour, $min, $sec, $mksec, $tz]
If any values in hash or array are absent (or = undef or = -1) the appropriate field of source date is not changed.
If tz
parameter is absent (or undef or ""), newly created date will use current date's timezone. Otherwise constructed date is converted to specified timezone preserving YMDhms information.
month_begin_new()
Returns the beggining of month. Only day of month is changed, HMS are preserved.
month_begin()
Same as month_begin_new()
but changes current object instead of cloning.
month_end_new()
Returns the end of month. Only day of month is changed, HMS are preserved.
month_end()
Same as month_end_new()
but changes current object instead of cloning.
days_in_month()
Returns the number of days in month
week_of_month()
Returns the week of the month [0..5]. The first week of the month is the first week that contains a Thursday. A day in the week before the week with the first Thursday will be week 0.
weeks_in_year()
Returns total number of weeks in the current year (52 or 53).
week_of_year()
my $week_number = $date->week_of_year();
my ($week_year, $week_number) = $date->week_of_year();
Returns information about the calendar week which contains this date object [1..53].
The first week of the year is defined by ISO as the one which contains the fourth day of January, which is equivalent to saying that it's the first week to overlap the new year by at least four days.
Typically the week year will be the same as the year that the object is in, but dates at the very beginning of a calendar year often end up in the last week of the prior year, and similarly, the final few days of the year may be placed in the first week of the next year.
error()
Returns error occured during creating or cloning object (if any) as XS::STL::ErrorCode object.
truncated()
Return copy of the current date with HMS set to 0. Same as clone(hour =
0, min => 0, sec => 0)>, but runs faster.
truncate()
Same as truncated()
but changes current object instead of cloning.
'<=>', 'cmp', compare($arg)
Converts $arg
to date, compares 2 dates and returns -1, 0 or 1.
$date <=> $arg
$arg <=> $date
$date <=> "2001-01-01 01:01:01"
$date <=> 123456789; # epoch
"01.02.2019" <=> $date
$date1 <=> $date2
'+', sum($arg)
Converts $arg
to relative date, adds it to the date and returns new date as a result.
$date + $arg
$arg + $date
$date + "1Y 2M";
86400 + $date;
$date + DAY;
'+=', add($arg)
Converts $arg
to relative date and adds it to existing date object.
$date += $arg
$date += 10;
$date += YEAR;
$date += "1h 2m 3s";
'-', difference($arg)
If second operand is a date object, then returns Date::Rel object representing exact interval from right operand till left operand.
$date_till - $date_from; # same as Date::Rel->new($date_from, $date_till)
(date("2019-02-01") - date("2019-01-01"))->to_days == 31;
see Date::Rel.
Otherwise converts right operand to relative date, subtracts it from the date object and returns new date as a result. Reverse is not allowed.
$date - "1Y";
$date - 86400;
86400 - $date; # !not allowed!
'-=', subtract($arg)
Converts $arg
to relative date and subtracts it from existing date object. Reverse is not allowed.
FUNCTIONS
now()
Same as Date->new(time()) but runs faster.
now_hires()
Same as Date->new(Time::HiRes::time()) but runs faster.
today()
Same as Date->new(time())->truncate but runs faster.
today_epoch()
Same as today()->epoch but runs faster.
range_check([$true_false])
If parts of the date are invalid or the whole date is not valid, e.g. 2001-02-31 then:
when range_check is not set (the default), then these date values are automatically converted to a valid date (normalized): 2001-03-03
when range_check is set, then a date "2001-02-31" became invalid date and error() is set to Date::Error::out_of_range
.
One exception from this rule is when format has a weekday name (rfc1123, etc) and it doesn't match represented date, Date::Error::out_of_range
will be always set.
date(...)
Same as Date->new(...). See new()
for arguments details.
date_ymd(...)
Same as Date->new_ymd(...). See new_ymd()
for arguments details.
rdate(...)
Same as Date::Rel->new(...), see Date::Rel
rdate_ymd(...)
Same as Date::Rel->new_ymd(...), see Date::Rel
tzget([$zone])
Returns timezone object for timezone name $zone
(or local zone if $zone is not provided). The object can later be used for creating dates in this zone without setting this zone as local via tzset()
.
tzset([$zone])
Sets $zone as localzone. If you don't provide $zone, default timezone will be set ($ENV{TZ}, /etc/localtime, or whatever your OS considers to be localzone).
Does NOT affect POSIX:tzset(). Only this module's functions and objects will follow this timezone.
# change local zone to 'America/New_York'
tzset('America/New_York');
# or
my $tz = tzget('America/New_York');
tzset($tz);
# the same (doesnt work in Windows)
local $ENV{TZ} = 'America/New_York';
tzset();
# change localzone back to the default localzone (in case you didn't change $ENV{TZ})
tzset(); # or tzset(undef) or tzset('')
If you don't want to change localzone, you don't have to call this function directly as it's called implicitly on-demand.
If you provide $zone and no such zone found in zones directory (or timezone file is corrupted), 'UTC0' is used.
$zone may be Date::Timezone object.
tzname()
The name of localzone. Note that in some cases the real name of localzone is not known (for example when localzone is retrieved from /etc/localtime file, tzname() will return ':/etc/localtime')
use_system_timezones()
Use your OS's timezones dir. This is default behaviour if your OS has /usr/share/zoneinfo DB. Otherwise embedded zones are used by default (for example, on MS Windows).
If your OS doesn't have /usr/share/zoneinfo DB, this function warns and does nothing.
use_embed_timezones()
Use timezone files which come with this module (they may be newer or older than system ones).
tzdir([$newdir])
Sets or returns current timezones directory. If there was an error (!exists, !readable, etc) returns false and leaves tzdir unchanged.
say tzdir(); # prints /usr/share/zoneinfo (on UNIX)
tzdir('/home/frank/myzones'); # use /home/frank/myzones as timezones DB
say tzdir(); # prints /home/frank/myzones
tzset('Europe/Moscow'); # set /home/frank/myzones/Europe/Moscow as localzone
available_timezones()
Returns list of all available timezones in tzdir().
strftime($format, $sec, $min, $hour, $mday, $mon, $year, [$isdst], [$timezone])
Works like POSIX's strftime()
, but runs much faster. Additionaly, supports timezone argument in which case it will interpret passed YMDHSD as date in timezone $timezone
instead of local zone.
NOTE: $year
must be in natural form (2019, not 119). Month as in original strftime()
, 0-11.
strftime($format, $epoch, [$timezone])
Same as above, but receives UNIX timestamp instead of YMDHMS arguments.
gmtime($epoch)
The returned year is in human-readable form (not year-1900). Month is [0-11]. The same applies for all further time functions.
localtime($epoch)
anytime($epoch, $timezone)
Like localtime()
but runs calculations in timezone $timezone
instead of local zone
timegm($sec, $min, $hour, $day, $mon, $year, [$isdst])
timegmn($sec, $min, $hour, $day, $mon, $year)
Same as timegm() except for the arguments which have to be non-constant values because they are normalized during calculations.
timelocal($sec, $min, $hour, $day, $mon, $year, [$isdst])
timelocaln($sec, $min, $hour, $day, $mon, $year, [$isdst])
Same as timelocal() except for the arguments which have to be non-constant values because they are normalized during calculations.
timeany($sec, $min, $hour, $day, $mon, $year, [$isdst], [$timezone])
Like timelocal()
but runs calculations in timezone $timezone
instead of local zone
timeanyn($sec, $min, $hour, $day, $mon, $year, [$isdst], [$timezone])
strptime($string, $format)
Parses date in $string
by the pattern defined in $format
. Works similar to strptime(3).
CONSTANTS
Date::Error::parser_error
Wrong date or relative date string format
Date::Error::out_of_range
Invalid date (or date part) supplied when range_check() is in effect
YEAR
Constant for rdate("1Y"). These (YEAR...SEC) objects are constants (read-only).
If you try to change these objects they'll croak.
MONTH
Constant for rdate("1M")
DAY
Constant for rdate("1D")
WEEK
Constant for rdate("1W")
HOUR
Constant for rdate("1h")
MIN
Constant for rdate("1m")
SEC
Constant for rdate("1s")
CLONING/SERIALIZATION
Date
supports:
- Storable serialization/deserealization
-
You can freeze Date::* objects and thaw serialized data back without losing any date information.
If you serialize a date object which was created with personal timezone (second arg to constructor), then it will be deserialized exactly in the same timezone.
If a date object is in local timezone, then it will be deserialized in local timezone too (which may differ on differrent servers), but it's guaranteed that those two dates will point to the same time moment (epoch is preserved).
For example:
tzset('Europe/Moscow'); my $date = date("2014-01-01"); my $frozen = freeze $date; tzset('America/New_York'); my $date2 = thaw $frozen; $date == $date2; # true, because $date->epoch == $date2->epoch say $date; # 2014-01-01 00:00:00 say $date2; # 2013-12-31 15:00:00
- Data::Recursive's
clone
- JSON serialization with convert_blessed
-
Serializes to
epoch()
PACKAGES
Date
(this package)
Date::Rel - relative date object
Date::strict - enable/disable strict mode
DATE RANGES
64bit OS + perl-64bit-int
from -2147483648/01/01 00:00:00 till 2147483647/12/31 23:59:59
32bit OS + perl-64bit-int
from -2147483648/01/01 00:00:00 till 2147483647/12/31 23:59:59
32bit OS + perl-32bit-int
from -285424812/02/20 18:53:48 till 285428751/11/12 11:36:32
Please note, that these ranges means that Date object can make calculations and its API works correctly while date is in these ranges.
However, it won't be able to parse and to stringify such dates because no ISO/RFC standarts exist for those ranges.
The maximum range for parsing and stringification is 0000/01/01 00:00:00 - 9999/12/31 23:59:59
SUPPORTED OS
Tested on FreeBSD, Linux, MacOSX, Windows 2003-10.
I believe all of UNIX-like and Windows-like systems are supported.
Timezones are supported in Olson DB format (V1,2,3).
CAVEATS
Setting $ENV{TZ}
doesn't work in Windows. To set $zone as localzone, you should write
Date::tzset($zone);
to produce platform-independent code.
Also please note that in some extremely rare cases the result of date calculations of this module and POSIX functions may not match (this module's results are correct in this case, POSIX's - are not).
That's because POSIX's timegm/timelocal/etc functions have bugs on some certain time moments. For detailed info see Date::TimeImpl.
PERFORMANCE
Date runs 1.5 - 50x faster than Time::Moment. Tests were performed on Xeon-v3 3.0Ghz, Debian 10, perl 5.30.0
new empty
Rate Time::Moment Date
Time::Moment 3619344/s -- -34%
Date 5450519/s 51% --
new with current time
Rate Time::Moment Date_hires Date
Time::Moment 420102/s -- -91% -92%
Date_hires 4812084/s 1045% -- -13%
Date 5519512/s 1214% 15% --
new from epoch
Rate Time::Moment Date
Time::Moment 3849666/s -- -25%
Date 5164206/s 34% --
new from string
Rate Time::Moment Date
Time::Moment 2682760/s -- -29%
Date 3780922/s 41% --
new from named YMDHMS
Rate Time::Moment Date
Time::Moment 2372854/s -- -13%
Date 2737056/s 15% --
today (now+truncate)
Rate Time::Moment Date
Time::Moment 430970/s -- -91%
Date 4721290/s 996% --
adding 1 relative
Rate Time::Moment Date
Time::Moment 3780922/s -- -53%
Date 7989875/s 111% --
adding many relatives
Rate Time::Moment Date
Time::Moment 1341380/s -- -72%
Date 4733156/s 253% --
converting epoch<->YMDHMS with date operations
Rate Time::Moment Date
Time::Moment 1102769/s -- -49%
Date 2143658/s 94% --
using timezones
Rate Time::Moment Date
Time::Moment 71087/s -- -98%
Date 3674915/s 5070% --
Benchmark code:
my $time = -1;
say "new empty";
cmpthese($time, {
Date => sub { Date::date() },
"Time::Moment" => sub { Time::Moment->new },
});
say;
say "new with current time";
cmpthese($time, {
Date => sub { Date::now() },
Date_hires => sub { Date::now_hires() },
"Time::Moment" => sub { Time::Moment->now },
});
say;
say "new from epoch";
cmpthese($time, {
Date => sub { Date::date(1000000000) },
"Time::Moment" => sub { Time::Moment->from_epoch(1000000000) },
});
say;
say "new from string";
cmpthese($time, {
Date => sub { Date::date("2019-01-01T23:59:59Z") },
"Time::Moment" => sub { Time::Moment->from_epoch("2019-01-01T23:59:59Z") },
});
say;
say "new from named YMDHMS";
cmpthese($time, {
Date => sub { Date::date_ymd(year => 2019, month => 1, day => 1, hour => 23, min => 59, sec => 59, mksec => 123456) },
"Time::Moment" => sub { Time::Moment->new(year => 2019, month => 1, day => 1, hour => 23, minute => 59, second => 59, nanosecond => 123456000) },
});
say;
say "today (now+truncate)";
{
my $d = Date::now();
my $tm = Time::Moment->now();
cmpthese($time, {
Date => sub { Date::today() },
"Time::Moment" => sub { Time::Moment->now->at_midnight },
});
}
say;
say "adding 1 relative";
{
my $d = Date::now();
my $tm = Time::Moment->now();
cmpthese($time, {
Date => sub { $d += HOUR },
"Time::Moment" => sub { $tm = $tm->plus_hours(1) },
});
}
say;
say "adding many relatives";
{
my $d = Date::now();
my $tm = Time::Moment->now();
cmpthese($time, {
Date => sub { $d += "1D 1h 1m 1s" },
"Time::Moment" => sub { $tm = $tm->plus_days(1)->plus_hours(1)->plus_minutes(1)->plus_seconds(1) },
});
}
say;
say "converting epoch<->YMDHMS with date operations";
{
my $d = Date::now();
my $tm = Time::Moment->now();
cmpthese($time, {
Date => sub { $d += 1; $d->year; $d += DAY; $d->epoch },
"Time::Moment" => sub { $tm = $tm->plus_seconds(1); $tm->year; $tm = $tm->plus_days(1); $tm->epoch },
});
}
say;
say "using timezones";
cmpthese($time, {
Date => sub { Date::date_ymd(2012, 12, 24, 15, 0, 0, 0, 'America/New_York') },
"Time::Moment" => sub {
my $tm = Time::Moment->new(
year => 2012,
month => 12,
day => 24,
hour => 15
);
my $zone = DateTime::TimeZone->new(name => 'America/New_York');
my $offset = $zone->offset_for_datetime($tm) / 60;
$tm->with_offset_same_instant($offset);
},
});
say;
AUTHOR
Pronin Oleg <syber@cpan.org>, Ivan Baidakou <i.baydakov@crazypanda.ru>, Crazy Panda LTD
LICENSE
You may distribute this code under the same terms as Perl itself.