William Allendoerfer
William Allendoerfer

Reputation: 61

Why does adding 6 days 7½ hours to midnight result in 8:30?

This example takes a base date and adds 7½ hours, 1 day 7½ hours, 2 days 7½ hours, and so on.

use Date::Manip;
use DateTime;
use DateTime::Format::DateManip;

Date::Manip::Date_Init("TZ=America/New_York", "Language=English");

my $otime = DateTime->new(
    year      => 2013,
    month     => 3,
    day       => 4,
    hour      => 0,
    minute    => 0,
    second    => 0,
    time_zone => 'America/New_York',
);

my $t1 = UnixDate($otime, "%i:%M %p on %A, %B %e, %Y ");
print "original $t1\n";

for (my $i = 0; $i <= 20; $i++) {               
    my $dtw = $otime->clone();
    $dtw->add(
        minutes => (15) * 30,
        days    => ($i),
    ); 
    $t1 = UnixDate($dtw, "%i:%M %p on %A, %B %e, %Y ");
    print "$i days $t1\n";
}

When adding 6 days 7½ hours, the result contains an extra hour.

original 12:00 AM on Monday, March 04, 2013
0 days 07:30 AM on Monday, March 04, 2013
1 days 07:30 AM on Tuesday, March 05, 2013
2 days 07:30 AM on Wednesday, March 06, 2013
3 days 07:30 AM on Thursday, March 07, 2013
4 days 07:30 AM on Friday, March 08, 2013
5 days 07:30 AM on Saturday, March 09, 2013
6 days 08:30 AM on Sunday, March 10, 2013    # why 8:30 and not 7:30?
7 days 07:30 AM on Monday, March 11, 2013
8 days 07:30 AM on Tuesday, March 12, 2013
9 days 07:30 AM on Wednesday, March 13, 2013
10 days 07:30 AM on Thursday, March 14, 2013
11 days 07:30 AM on Friday, March 15, 2013
12 days 07:30 AM on Saturday, March 16, 2013
13 days 07:30 AM on Sunday, March 17, 2013
14 days 07:30 AM on Monday, March 18, 2013
15 days 07:30 AM on Tuesday, March 19, 2013
16 days 07:30 AM on Wednesday, March 20, 2013
17 days 07:30 AM on Thursday, March 21, 2013
18 days 07:30 AM on Friday, March 22, 2013
19 days 07:30 AM on Saturday, March 23, 2013
20 days 07:30 AM on Sunday, March 24, 2013

Upvotes: 6

Views: 261

Answers (1)

cjm
cjm

Reputation: 62109

Because Daylight Saving Time begins on March 10, 2013 in the America/New_York timezone. DateTime first adds $i days (to get midnight on March 10) and then adds 450 minutes to get 8:30 AM (because the minute after 1:59 AM on March 10 is 3:00 AM). The order of the parameters to add is not meaningful; see Adding a Duration to a Datetime.

Because it adds days & minutes separately (and processes the days first), the effect only happens on the date when DST actually begins or ends. If you want a particular time, just set it directly instead of using add. Or call add twice, once to add minutes, then again to add days.

Upvotes: 18

Related Questions