Reputation: 1129
Smallest example:
var test = new Date();
test.setMonth(3);
test.setDate(3);
test.setHours(2);
test.getUTCHours()`
On Firefox I get "7" and Chrome gives me "8" (what I consider the correct answer).
DST is approaching and I've been tasked with fixing various issues with change in our javascript. I'm not sure how to handle this though. The time is moving forward 1 hour so at we will go from 1:59:59 to 3:00:00 skipping 2am completely. The problem is we have multiple datetime pickers that have no concepts of this (and that's ok) and so you can still select 2am times. I would expect when I construct a date from a 2am time that it would get pushed to 3am so 2:05 becomes 3:05. Chrome handles this just fine however Firefox appears to push it back to 1:05. The UTC are off by one hour however when you format with a timezone it will appear as 1:05.
How can I work around this? I think the answer is just "momentjs" but I want to understand why this is different.
Upvotes: 2
Views: 869
Reputation: 241573
You are correct. The Spring Forward DST transition will create a gap of invalid local time. JavaScript will either advance it forward it backward, by the amount of the gap. Which direction it goes is not defined in the ECMAScript specification, and thus different browsers do it differently. IMHO, moving forward makes the most logical sense (since time moves forward), but some feel that using "standard" time should be prefered.
For the Fall Back DST transition, there is a period of overlapping local time, where a local time may be ambiguous. JavaScript will either map it to the first instance (daylight time), or the second instance (standard time). Again, some feel that "standard" time should be prefered, but it makes more logical sense to go in the order that time actually occurs - which means choosing the daylight instance.
Here's how the landscape currently looks for desktop browsers:
I've updated these charts many times over the last few years, as it even within browsers it has changed between versions. The first versions I made for my Pluralsight course looked quite different. Many of the browsers have flipped from one side of the behavior to the other. So be careful about making any assumptions - older browsers could very well have differences from this chart. I also didn't show the vast array of mobile web browsers out there.
Now you asked about how to deal with this problem. Unfortunately, there aren't a lot of good options. You mentioned moment.js, which is indeed a great library for dates and times - but since it presently relies on the Date
object under the hood, it does not solve this particular problem. It inherits whatever behavior the browser has. (This is a known issue, and we're working on it.)
I previously had written some functions to show how to work around the problem. You can still find these if you review the edit history. Unfortunately, I made one critical mistake with the isShiftedForward
and isShiftedBackward
methods. Though they returned true
if a timestamp had been shifted, they also returned true (incorrectly) when given a valid timestamp immediately adjacent to the transition. (That is, in the hour following when shifting forward, or the hour preceding when shifting backward.)
Therefore, I've removed these functions from the answer. There's no way to avoid this without knowing the original values that created the Date
object. They can't work from the Date
object alone.
Upvotes: 5