NAME
Date::Tie - ISO dates made easy
SYNOPSIS
use Date::Tie;
tie my %date, 'Date::Tie', year => 2001, month => 11, day => 9;
$date{year}++;
$date{month} += 12; # 2003-11-09
# you can also use OO syntax
my $date = Date::Tie->new( year => 2001, month => 11, day => 9 );
$date->{year}++;
$date->{month} += 12; # 2003-11-09
$date{weekday} = 0; # sunday at the start of this week
$date{weekday} = 7; # sunday at the end of this week
$date{weekday} = 14; # sunday next week
$date{tz} = '-0300'; # change timezone
$date{tzhour}++; # increment timezone
# "next month's last day"
$date{month}+=2;
$date{day} = 0; # this is actually a "-1" since days start in "1"
# copy a date with timezone
tie my %newdate, 'Date::Tie', tz => $date{tz}, epoch => $date{epoch};
or
tie my %newdate, 'Date::Tie', %date;
DESCRIPTION
Date::Tie is an attempt to simplify date operations syntax.
It works with calendar dates (year-month-day), ordinal dates (year-day), week dates (year-week-day), times (hour:minute:second), decimal fractions (decimal hours, decimal minutes and decimal seconds), and time-zones.
Whenever a Date::Tie hash key receives a new value, it will change the other keys following the ISO date rules. For example:
print $a{hour}, ":", $a{minute}; # '00:59'
$a{minute}++;
print $a{hour}, ":", $a{minute}; # '01:00'
DEFAULT VALUE
The default value of a new hash is the current value of gmtime(), with timezone +0000
and with fractional seconds set to zero.
HASH KEYS
Date::Tie manages a hash containing the keys:
year, month, day, hour, minute, second, yearday, week, weekday, weekyear, epoch, utc_epoch, tz, tzhour, tzminute, frac_hour, frac_minute, frac_second, frac_epoch, frac.
All keys can be read and written to.
- year, month, day or monthday, hour, minute, second
-
These keys are just what they say.
You can use monthday instead of day if you want to make it clear it is not a yearday (ordinal calendar) or a weekday (week calendar).
- yearday, week, weekday, weekyear
-
yearday is the day number in the year.
weekday is the day number in the week. weekday
1
is monday.week is the week number in the year.
weekyear is the year number, when referring to a week of a year. It is often not equal to year. Changing weekyear will leave you with the same week and weekday, while changing year will leave you with the same month and monthday.
- epoch
-
epoch is an internal notation and is not a part of the ISO8601 standard.
This value is system-dependent, and it might overflow for dates outside the years 1970-2038.
epoch is the local epoch. That is, time
20020101T000000+0300
is the same epoch as20020101T000000+0600
. - utc_epoch
-
The system epoch in UTC time, that is, in timezone
+0000
.See also the
epoch
key. - tz, tzhour, tzminute
-
tz is the timezone as hundreds, like in
-0030
. It is not always the same as the expression$date{tzhour} . $date{tzminute}
, which in this case would be-00-30
.Changing timezone (any of tz, tzhour, or tzminute) changes epoch.
- frac_hour, frac_minute, frac_second, frac_epoch
-
These keys are used for fractional decimal notation:
$d{hour} = 13; $d{minute} = 30; # 0.5 hour $d{second} = 00; print $d{frac_hour}; # '13.5' $d{frac_minute} = 17.3; print "$d{minute}:$d{second}"; # '17:18' $d{frac_minute} -= 0.2; print "$d{minute}:$d{second}"; # '17:06' $d{epoch} = 1234567; $d{frac} = 0.7654321; print $d{frac_epoch}; # '1234567.7654321'
- frac
-
Fractional seconds. A value bigger or equal to 0 and less than 1 second.
$d{frac} = 0.5; print $d{frac}; # '.5' $d{frac} = 0; print $d{frac}; # '.0'
Setting frac does not change second or epoch, unless it overflows:
$d{second} = 6; print $d{second}; # '06' $d{frac} = 1.5; print $d{second}; # '07' - frac overflow print $d{frac}; # '.5'
To obtain the fractional second or epoch:
print "$d{second}$d{frac}"; # '07.5' - concatenation print $d{second} + $d{frac}; # '7.5' - addition print $d{epoch} + $d{frac}; # '45673455.5' - fractional epoch
See also: frac_epoch and frac_second.
BASIC ISO8601
Day of year starts with 001
.
Day of week starts with 1
and is a monday.
Week starts with 01
and is the first week of the year that has a thursday. Week 01
often begins in the previous year.
CAVEATS
Since Date::Tie
is based on gmtime()
and timegm()
, it is expected to work only on years between 1970 and 2038 (this is system-dependent).
Reading time zone -0030
with $date{tzhour} . $date{tzminute}
gives -00-30
. Use tz to get -0030
.
The order of setting hash elements is important, since changing the timezone will change the hour.
These are some ways to make a copy of %d
:
# copy all fields
# hash %d MUST be tied do Date::Tie, if you are using timezones
tie my %b, 'Date::Tie', %d;
# set timezone, then epoch, ignoring fractional seconds
tie my %b, 'Date::Tie', tz => $d{tz}, epoch => $d{epoch};
# set timezone, then epoch and fractional seconds
tie my %b, 'Date::Tie', tz => $d{tz}, epoch => $d{epoch}, frac => $d{frac};
# set timezone, then fractional epoch
tie my %b, 'Date::Tie', tz => $d{tz}, frac_epoch => $d{frac_epoch};
In OO style you can use new
to make a copy:
# make a copy of object
my $b = $d->new;
# make a copy of object, then set the copy to next month
($b = $d->new)->{month}++;
# make a copy of object, then set the copy to month 3
$b = $d->new(month => 3);
If you change month, then day will be adjusted to fit that month:
$date = (month=>10, day=>31);
$date{month}++; # month=>11, day=>30
If you need to know whether a hash is tied to Date::Tie use perl function tied()
SEE ALSO
DateTime and http://datetime.perl.org
Date::Calc, Date::Manip, Class::Date, and many other good date and time modules!
Date::Tie depends on Tie::Hash, Time::Local and POSIX.
dmoz section on ISO8601 at http://dmoz.org/Science/Reference/Standards/Individual_Standards/ISO_8601/
Markus Kuhn wrote a summary of ISO8601 International Standard Date and Time Notation, that can be found at http://www.cl.cam.ac.uk/~mgk25/iso-time.html
AUTHOR
Flávio Soibelmann Glock (fglock@gmail.com)
CREDITS
Original idea based on a mail by dLux.
Eduardo M. Cavalcanti, Henrique Pantarotto and Jean contributed bugfixes.
Dan Wright created the utc_epoch
key.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 656:
Non-ASCII character seen before =encoding in 'Flávio'. Assuming CP1252