DateTime

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    If you do not care about time zones or leap seconds, use the "floating"
    timezone:

        my $dt = DateTime->now( time_zone => 'floating' );

    Math done on two objects in the floating time zone produces very predictable
    results.

    Note that in most cases you will want to start by creating an object in a
    specific zone and _then_ convert it to the floating time zone. When an object
    goes from a real zone to the floating zone, the time for the object remains the
    same.

    This means that passing the floating zone to a constructor may not do what you
    want.

        my $dt = DateTime->now( time_zone => 'floating' );

    is equivalent to

        my $dt = DateTime->now( time_zone => 'UTC' )->set_time_zone('floating');

    This might not be what you wanted. Instead, you may prefer to do this:

        my $dt = DateTime->now( time_zone => 'local' )->set_time_zone('floating');

- use UTC for all calculations

    If you do care about time zones (particularly DST) or leap seconds, try to use
    non-UTC time zones for presentation and user input only. Convert to UTC
    immediately and convert back to the local time zone for presentation:

        my $dt = DateTime->new( %user_input, time_zone => $user_tz );
        $dt->set_time_zone('UTC');

        # do various operations - store it, retrieve it, add, subtract, etc.

        $dt->set_time_zone($user_tz);
        print $dt->datetime;

- math on non-UTC time zones

    If you need to do date math on objects with non-UTC time zones, please read the
    caveats below carefully. The results `DateTime` produces are predictable,
    correct, and mostly intuitive, but datetime math gets very ugly when time zones
    are involved, and there are a few strange corner cases involving subtraction of
    two datetimes across a DST change.

    If you can always use the floating or UTC time zones, you can skip ahead to
    ["Leap Seconds and Date Math"](#leap-seconds-and-date-math)

- date vs datetime math

    If you only care about the date (calendar) portion of a datetime, you should
    use either `$dt->delta_md` or `$dt->delta_days`, not `$dt->subtract_datetime`. This will give predictable, unsurprising results,
    free from DST-related complications.

- $dt->subtract\_datetime and $dt->add\_duration

    You must convert your datetime objects to the UTC time zone before doing date
    math if you want to make sure that the following formulas are always true:

        $dt2 - $dt1 = $dur
        $dt1 + $dur = $dt2
        $dt2 - $dur = $dt1

    Note that using `$dt->delta_days` ensures that this formula always works,
    regardless of the time zones of the objects involved, as does using `$dt->subtract_datetime_absolute`. Other methods of subtraction are not always
    reversible.

- never do math on two objects where only one is in the floating time zone

    The date math code accounts for leap seconds whenever the `DateTime` object is
    not in the floating time zone. If you try to do math where one object is in the
    floating zone and the other isn't, the results will be confusing and wrong.

### Adding a Duration to a DateTime

The parts of a duration can be broken down into five parts. These are months,
days, minutes, seconds, and nanoseconds. Adding one month to a date is
different than adding 4 weeks or 28, 29, 30, or 31 days.  Similarly, due to DST
and leap seconds, adding a day can be different than adding 86,400 seconds, and
adding a minute is not exactly the same as 60 seconds.

We cannot convert between these units, except for seconds and nanoseconds,
because there is no fixed conversion between most pairs of units. That is
because of things like leap seconds, DST changes, etc.

`DateTime` always adds (or subtracts) days, then months, minutes, and then
seconds and nanoseconds. If there are any boundary overflows, these are
normalized at each step. For the days and months the local (not UTC) values are
used. For minutes and seconds, the local values are used. This generally just
works.

This means that adding one month and one day to February 28, 2003 will produce
the date April 1, 2003, not March 29, 2003.

    my $dt = DateTime->new( year => 2003, month => 2, day => 28 );

    $dt->add( months => 1, days => 1 );

    # 2003-04-01 - the result

On the other hand, if we add months first, and then separately add days, we end
up with March 29, 2003:

    $dt->add( months => 1 )->add( days => 1 );

    # 2003-03-29

We see similar strangeness when math crosses a DST boundary:

    my $dt = DateTime->new(
        year      => 2003,
        month     => 4,
        day       => 5,
        hour      => 1,
        minute    => 58,
        time_zone => "America/Chicago",
    );

    $dt->add( days => 1, minutes => 3 );
    # 2003-04-06 02:01:00

    $dt->add( minutes => 3 )->add( days => 1 );
    # 2003-04-06 03:01:00



( run in 2.198 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )