# 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

instead of*monthday**day*if you want to make it clear it is not a*yearday*(ordinal calendar) or a*weekday*(week calendar). *yearday*,*week*,*weekday*,*weekyear*-
is the day number in the year.*yearday*is the day number in the week.*weekday**weekday*`1`

is monday.is the week number in the year.*week*is the year number, when referring to a week of a year. It is often*weekyear**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*-
is an internal notation and is not a part of the ISO8601 standard.*epoch*This value is system-dependent, and it might overflow for dates outside the years 1970-2038.

is the local epoch. That is, time*epoch*`20020101T000000+0300`

is the same epoch as`20020101T000000+0600`

. *utc_epoch*-
The system epoch in UTC time, that is, in timezone

`+0000`

.See also the

`epoch`

key. *tz*,*tzhour*,*tzminute*-
is the timezone as hundreds, like in*tz*`-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 ISO8859-1