views:

65

answers:

1

I'm seeing some behavior I don't understand with Javascript date objects and DST transitions. If I execute the following in Chrome's javascript console

var date = new Date(1268535600000); //2010-03-14T03:00:00.000Z (21:00 03-13 America/Chicago) 
for(var i = 1; i <= 12; i++)
{   
    var time = date.getHours();
    console.log(time)
    console.log(date)
    date.setHours(date.getHours() + 1);         
}

the output is:

21
Sat Mar 13 2010 21:00:00 GMT-0600 (Central Standard Time)
22
Sat Mar 13 2010 22:00:00 GMT-0600 (Central Standard Time)
23
Sat Mar 13 2010 23:00:00 GMT-0600 (Central Standard Time)
0
Sun Mar 14 2010 00:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)

However, changing the last line of the for loop to

date = new Date(date.getTime() + 3600000)   

produces the output I'd expect with the skipped hour at the transition:

21
Sat Mar 13 2010 21:00:00 GMT-0600 (Central Standard Time)
22
Sat Mar 13 2010 22:00:00 GMT-0600 (Central Standard Time)
23
Sat Mar 13 2010 23:00:00 GMT-0600 (Central Standard Time)
0
Sun Mar 14 2010 00:00:00 GMT-0600 (Central Standard Time)
1
Sun Mar 14 2010 01:00:00 GMT-0600 (Central Standard Time)
3
Sun Mar 14 2010 03:00:00 GMT-0500 (Central Daylight Time)
4
Sun Mar 14 2010 04:00:00 GMT-0500 (Central Daylight Time)
5
Sun Mar 14 2010 05:00:00 GMT-0500 (Central Daylight Time)
6
Sun Mar 14 2010 06:00:00 GMT-0500 (Central Daylight Time)
7
Sun Mar 14 2010 07:00:00 GMT-0500 (Central Daylight Time)
8
Sun Mar 14 2010 08:00:00 GMT-0500 (Central Daylight Time)
9
Sun Mar 14 2010 09:00:00 GMT-0500 (Central Daylight Time)

What is the reason the the first approach doesn't work?

Edit: Additionally, with a DST transition with a duplicated hour it seems to just ignore the duplicated hour with the first approach: The other thing is that if I try it with a DST transition with a duplicated hour it just seems to ignore the duplicated hour:

Sun Nov 07 2010 00:00:00 GMT-0500 (Central Daylight Time)
Sun Nov 07 2010 01:00:00 GMT-0600 (Central Standard Time)
Sun Nov 07 2010 02:00:00 GMT-0600 (Central Standard Time)

But it correctly handles the duplicated hour with the second approach.

+1  A: 

Maybe it's a bug. Have you tried it on more than one browser?

Otherwise I'd guess that since you're trying to set the hours to a time that doesn't exist, it rejects the change.

Mark Ransom
Yes, I get the same behavior in Firefox using Firebug as the console.
Will Gorman
I'm not sure if it's just due to the invalid time since there's also some strangeness with a DST transition with a repeated hour (I updated the question with that case)
Will Gorman
@Will, your new case doesn't change my answer at all. The Fall transition doesn't contain any invalid times, it just doubles up an hour: 01:00 to 01:59 happens twice. It's interesting that it chooses CST rather than keeping the previous value of CDT, but both answers are correct. For the Spring transition, 02:00 to 02:59 don't exist, so setting the time anywhere in that interval would be an error.
Mark Ransom
The more I think about it, the more this behavior makes sense. I guess the best course of action is to work internally in UTC and use the conversion to local time only for displaying data to the user. The real WTF is DST.
eBusiness
@eBusiness, UTC is almost always the best answer. It's unambiguous and monotonic.
Mark Ransom
I guess I can see it making sense that adding hours to the date that's already in the timezone with the DST change would be interpreted as an invalid time while creating a new date from milliseconds would work since that represents a UTC time that's then converted to a valid local time. It just seems like a poor design choice in the javascript date API since it seems reasonable to expect that adding hours would do something sensible with the DST transition.
Will Gorman
@Will, from the perspective of the date object you're not adding an hour, you're setting the hour to an arbitrary value. Your second example *is* adding an hour, so it does the sensible thing.
Mark Ransom
Is it really though? If it were just setting the hour to an arbitrary value instead of adding an hour I would expect that adding an hour at 23:00 wouldn't roll over to the next day as it does.
Will Gorman