38local-subtract.t [plain text]
use strict;
use Test::More tests => 127;
use DateTime;
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 11, day => 6,
time_zone => 'America/Chicago',
);
my $dur1 = $dt2->subtract_datetime($dt1);
my %deltas1 = $dur1->deltas;
is( $deltas1{months}, 6, 'delta_months is 6' );
is( $deltas1{days}, 0, 'delta_days is 0' );
is( $deltas1{minutes}, 0, 'delta_minutes is 0' );
is( $deltas1{seconds}, 0, 'delta_seconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0,
'subtract_datetime is reversible from start point' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0,
'subtract_datetime is reversible from end point' );
is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' );
my $dur2 = $dt1->subtract_datetime($dt2);
my %deltas2 = $dur2->deltas;
is( $deltas2{months}, -6, 'delta_months is -6' );
is( $deltas2{days}, 0, 'delta_days is 0' );
is( $deltas2{minutes}, 0, 'delta_minutes is 0' );
is( $deltas2{seconds}, 0, 'delta_seconds is 0' );
is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' );
my $dur3 = $dt2->delta_md($dt1);
my %deltas3 = $dur3->deltas;
is( $deltas3{months}, 6, 'delta_months is 6' );
is( $deltas3{days}, 0, 'delta_days is 0' );
is( $deltas3{minutes}, 0, 'delta_minutes is 0' );
is( $deltas3{seconds}, 0, 'delta_seconds is 0' );
is( $deltas3{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0,
'delta_md is reversible from start point' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur3), $dt1 ), 0,
'delta_md is reversible from end point' );
my $dur4 = $dt2->delta_days($dt1);
my %deltas4 = $dur4->deltas;
is( $deltas4{months}, 0, 'delta_months is 0' );
is( $deltas4{days}, 184, 'delta_days is 184' );
is( $deltas4{minutes}, 0, 'delta_minutes is 0' );
is( $deltas4{seconds}, 0, 'delta_seconds is 0' );
is( $deltas4{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur3), $dt2 ), 0,
'delta_days is reversible from start point' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur4), $dt1 ), 0,
'delta_days is reversible from end point' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6, hour => 18,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 11, day => 6, hour => 18,
time_zone => 'America/Chicago',
);
my $dur1 = $dt2->subtract_datetime($dt1);
my %deltas1 = $dur1->deltas;
is( $deltas1{months}, 6, 'delta_months is 6' );
is( $deltas1{days}, 0, 'delta_days is 0' );
is( $deltas1{minutes}, 0, 'delta_minutes is 0' );
is( $deltas1{seconds}, 0, 'delta_seconds is 0' );
is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 11, day => 6,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2004, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dur1 = $dt2->delta_md($dt1);
my %deltas1 = $dur1->deltas;
is( $deltas1{months}, 6, 'delta_months is 6' );
is( $deltas1{days}, 0, 'delta_days is 0' );
is( $deltas1{minutes}, 0, 'delta_minutes is 0' );
is( $deltas1{seconds}, 0, 'delta_seconds is 0' );
is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' );
my $dur2 = $dt2->delta_days($dt1);
my %deltas2 = $dur2->deltas;
is( $deltas2{months}, 0, 'delta_months is 0' );
is( $deltas2{days}, 182, 'delta_days is 182' );
is( $deltas2{minutes}, 0, 'delta_minutes is 0' );
is( $deltas2{seconds}, 0, 'delta_seconds is 0' );
is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 11, day => 6,
time_zone => 'America/Chicago',
);
$dt1->set_time_zone('UTC');
$dt2->set_time_zone('UTC');
my $dur = $dt2->subtract_datetime($dt1);
is( DateTime->compare( $dt1->add_duration($dur), $dt2 ), 0,
'subtraction is reversible from start point with UTC' );
is( DateTime->compare( $dt2->subtract_duration($dur), $dt2 ), 0,
'subtraction is reversible from start point with UTC' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 11, day => 6,
time_zone => 'America/Chicago',
);
my $dur1 = $dt2->subtract_datetime_absolute($dt1);
my %deltas1 = $dur1->deltas;
is( $deltas1{months}, 0, 'delta_months is 0' );
is( $deltas1{days}, 0, 'delta_days is 0' );
is( $deltas1{minutes}, 0, 'delta_minutes is 0' );
is( $deltas1{seconds}, 15901200, 'delta_seconds is 15901200' );
is( $deltas1{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur1), $dt2 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur1), $dt1 ), 0,
'subtraction is doubly reversible' );
my $dur2 = $dt1->subtract_datetime_absolute($dt2);
my %deltas2 = $dur2->deltas;
is( $deltas2{months}, 0, 'delta_months is 0' );
is( $deltas2{days}, 0, 'delta_days is 0' );
is( $deltas2{minutes}, 0, 'delta_minutes is 0' );
is( $deltas2{seconds}, -15901200, 'delta_seconds is -15901200' );
is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt2->clone->add_duration($dur2), $dt1 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0,
'subtraction is doubly reversible' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 4, day => 6,
hour => 1, minute => 58,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 4, day => 6,
hour => 3, minute => 1,
time_zone => 'America/Chicago',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, 'delta_months is 0' );
is( $deltas{days}, 0, 'delta_days is 0' );
is( $deltas{minutes}, 3, 'delta_minutes is 3' );
is( $deltas{seconds}, 0, 'delta_seconds is 0' );
is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1), 0,
'subtraction is doubly reversible' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 4, day => 5,
hour => 1, minute => 58,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 4, day => 6,
hour => 3, minute => 1,
time_zone => 'America/Chicago',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, 'delta_months is 0' );
is( $deltas{days}, 1, 'delta_days is 1' );
is( $deltas{minutes}, 3, 'delta_minutes is 3' );
is( $deltas{seconds}, 0, 'delta_seconds is 0' );
is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'dt1 + dur = dt2' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur),
$dt1->clone->add( hours => 1 ) ),
0,
'dt2 - dur != dt1 (not reversible)' );
is( DateTime->compare( $dt2->clone->subtract_duration( $dur->clock_duration )
->subtract_duration( $dur->calendar_duration ),
$dt1 ),
0,
'dt2 - dur->clock - dur->cal = dt1 (reversible when componentized)' );
my $dur2 = $dt1->subtract_datetime($dt2);
my %deltas2 = $dur2->deltas;
is( $deltas2{months}, 0, 'delta_months is 0' );
is( $deltas2{days}, -1, 'delta_days is 1' );
is( $deltas2{minutes}, -3, 'delta_minutes is 3' );
is( $deltas2{seconds}, 0, 'delta_seconds is 0' );
is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( $dt2->clone->add_duration($dur2)->datetime, '2003-04-05T02:58:00', 'dt2 + dur2 != dt1' );
is( DateTime->compare( $dt2->clone->add_duration( $dur2->clock_duration )
->add_duration( $dur2->calendar_duration ),
$dt1 ),
0,
'dt2 + dur2->clock + dur2->cal = dt1' );
is( DateTime->compare( $dt1->clone->subtract_duration($dur2), $dt2 ), 0,
'dt1 - dur2 = dt2' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 4, day => 6,
hour => 3, minute => 1,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 4, day => 7,
hour => 3, minute => 2,
time_zone => 'America/Chicago',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, 'delta_months is 0' );
is( $deltas{days}, 1, 'delta_days is 1' );
is( $deltas{minutes}, 1, 'delta_minutes is 1' );
is( $deltas{seconds}, 0, 'delta_seconds is 0' );
is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' );
my $dur2 = $dt1->subtract_datetime($dt2);
my %deltas2 = $dur2->deltas;
is( $deltas2{months}, 0, 'delta_months is 0' );
is( $deltas2{days}, -1, 'delta_days is -1' );
is( $deltas2{minutes}, -1, 'delta_minutes is -1' );
is( $deltas2{seconds}, 0, 'delta_seconds is 0' );
is( $deltas2{nanoseconds}, 0, 'delta_nanoseconds is 0' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 4, day => 5,
hour => 1, minute => 58,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 4, day => 7,
hour => 2, minute => 1,
time_zone => 'America/Chicago',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, 'delta_months is 0' );
is( $deltas{days}, 2, 'delta_days is 2' );
is( $deltas{minutes}, 3, 'delta_minutes is 3' );
is( $deltas{seconds}, 0, 'delta_seconds is 0' );
is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0,
'subtraction is doubly reversible' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dt2 = DateTime->new( year => 2003, month => 11, day => 6,
time_zone => 'America/Chicago',
);
$dt1->set_time_zone('floating');
$dt2->set_time_zone('floating');
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 6, 'delta_months is 6' );
is( $deltas{days}, 0, 'delta_days is 0' );
is( $deltas{minutes}, 0, 'delta_minutes is 0' );
is( $deltas{seconds}, 0, 'delta_seconds is 0' );
is( $deltas{nanoseconds}, 0, 'delta_nanoseconds is 0' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'subtraction is reversible from start point' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0,
'subtraction is reversible from end point' );
}
{
my $dt1 = DateTime->new( year => 2005, month => 8,
time_zone => 'Europe/London',
);
my $dt2 = DateTime->new( year => 2005, month => 11,
time_zone => 'Europe/London',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 3, '3 months between two local times over DST change' );
is( $deltas{days}, 0, '0 days between two local times over DST change' );
is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' );
}
{
my $dt1 = DateTime->new( year => 2005, month => 8, hour => 12,
time_zone => 'Europe/London',
);
my $dt2 = DateTime->new( year => 2005, month => 11, hour => 12,
time_zone => 'Europe/London',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 3, '3 months between two local times over DST change' );
is( $deltas{days}, 0, '0 days between two local times over DST change' );
is( $deltas{minutes}, 0, '0 minutes between two local times over DST change' );
}
{
my $dt2 = DateTime->new( year => 2003, month => 10, day => 26,
hour => 1,
time_zone => 'America/Chicago',
);
my $dt1 = $dt2->clone->subtract( hours => 1 );
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, '0 months between two local times over DST change' );
is( $deltas{days}, 0, '0 days between two local times over DST change' );
is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0,
'subtraction is doubly reversible' );
}
{
my $dt1 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/New_York',
);
my $dt2 = DateTime->new( year => 2003, month => 5, day => 6,
time_zone => 'America/Chicago',
);
my $dur = $dt2->subtract_datetime($dt1);
my %deltas = $dur->deltas;
is( $deltas{months}, 0, '0 months between two local times over DST change' );
is( $deltas{days}, 0, '0 days between two local times over DST change' );
is( $deltas{minutes}, 60, '60 minutes between two local times over DST change' );
is( DateTime->compare( $dt1->clone->add_duration($dur), $dt2 ), 0,
'subtraction is reversible' );
is( DateTime->compare( $dt2->clone->subtract_duration($dur), $dt1 ), 0,
'subtraction is doubly reversible' );
}
{
my $dt1 = DateTime->new( year => 2005, month => 4, day => 3,
hour => 7, minute => 0,
time_zone => 'America/New_York' );
my $dt2 = DateTime->new( year => 2005, month => 4, day => 3,
hour => 8, minute => 0,
time_zone => 'America/New_York' );
my $dur = $dt2->subtract_datetime($dt1);
my ( $minutes, $seconds ) = $dur->in_units( 'minutes','seconds' );
is( $minutes, 60, 'subtraction of two dates on a DST change date, minutes == 60' );
is( $seconds, 0, 'subtraction of two dates on a DST change date, seconds == 0' );
$dur = $dt1->subtract_datetime($dt1);
ok( $dur->is_zero, 'dst change date (no dst) - itself, duration is zero' );
}
{
my $dt1 = DateTime->new( year => 2005, month => 4, day => 3,
hour => 1, minute => 0,
time_zone => 'America/New_York' );
my $dur = $dt1->subtract_datetime($dt1);
ok( $dur->is_zero, 'dst change date (with dst) - itself, duration is zero' );
}
{
my $dt1 = DateTime->new( year => 2009, month => 3, day => 9,
time_zone => 'America/New_York' );
my $dt2 = DateTime->new( year => 2009, month => 3, day => 9,
time_zone => 'Asia/Hong_Kong' );
my $dur = $dt1->subtract_datetime($dt2);
is( $dur->delta_minutes, 720,
'subtraction the day after a DST change in one zone, where the other datetime is in a different zone' );
}
{
my $dt1 = DateTime->new( year => 2009, month => 3, day => 8,
hour => 1,
time_zone => 'America/New_York' );
my $dt2 = DateTime->new( year => 2009, month => 3, day => 8,
hour => 1,
time_zone => 'Asia/Hong_Kong' );
my $dur = $dt1->subtract_datetime($dt2);
is( $dur->delta_minutes, 780,
'subtraction the day of a DST change in one zone (before the change),'
. ' where the other datetime is in a different zone' );
}
{
my $dt1 = DateTime->new( year => 2009, month => 3, day => 8,
hour => 4,
time_zone => 'America/New_York' );
my $dt2 = DateTime->new( year => 2009, month => 3, day => 8,
hour => 4,
time_zone => 'Asia/Hong_Kong' );
my $dur = $dt1->subtract_datetime($dt2);
is( $dur->delta_minutes, 720,
'subtraction the day of a DST change in one zone (after the change),'
. ' where the other datetime is in a different zone' );
}