Gordon Kushner
Gordon Kushner

Reputation: 165

JavaScript date quirk

This is the strangest behavior I have witnessed in JavaScript.

Under a very specific set of circumstances, this code will yield a time that's 40 minutes and 28 seconds earlier:

var jsDate = new Date('01/01/1900 11:00:00');
jsDate.setSeconds(0);
var dateString = jsDate.toLocaleTimeString("en", {
    hour12 : false
});
alert(dateString); //dateString will be 10:19:32

This happens for one site in the Netherlands but not for our developer there. It happens on Firefox and Chrome. The workstation is Windows 7.

Testing it, I found that the broken result happens for any year prior to 1942. For 1943 and 1944, it adds an hour.

Every year after that works fine, regardless of the date format: 01/01/1900 and 1900-01-01.

Background for the curious:

We have a date time widget and are only interested in the time portion.

The fix is to set the dummy date to 2000. But we are boggled about the "why".

Link to jsFiddle

This issue is not related to UTC vs Localized time. The strangest feature is that it alters the time by minutes and seconds, not hours.

Upvotes: 2

Views: 184

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241890

I'll stick to your Netherlands example that was returning 10:19:32, and address the why part of this question.

The time zone database entry for Europe/Amsterdam is here, and looks like this:

# Zone NAME            GMTOFF   RULES   FORMAT       [UNTIL]
Zone Europe/Amsterdam  0:19:32  -       LMT          1835
                       0:19:32  Neth    %s           1937 Jul  1
                       0:20     Neth    +0020/+0120  1940 May 16  0:00
                       1:00     C-Eur   CE%sT        1945 Apr  2  2:00
                       1:00     Neth    CE%sT        1977
                       1:00     EU      CE%sT

Since you passed a date in 1900, the second line applies, which has an offset from UTC of 0:19:32, which happens to coincide with the Local Mean Time (LMT) entry above it.

As Chris Pearce explains in The Great Daylight Saving Time Controversy:

... All this was in a country that hadn't yet adopted standard time. Controversy had raged in the Netherlands over whether it should use GMT and turn clocks back about 20 minutes or use GMT+1 and go forward 40 minutes. Agreement couldn't be reached, so they stayed on local time long after all other European countries had moved to standard time. Local mean time of capital city Amsterdam, GMT+0:19:32, had been used nationwide for decades and this became the legal time ...

With regard to other time zones, you're likely hitting on their own interesting bits of history, or just on the Local Mean Time entry in the TZDB, which is usually the earliest entry and is used when there is no other history known about timekeeping in the region.

The lesson here is that time zones are a relatively modern invention, and have often been a point of political controversy. Don't assume that because you know how they work today that your knowledge will apply to the past. Keep in mind also that as various tidbits of history are uncovered, the TZDB is updated accordingly, so indeed history can change!

In general, expect to encounter oddities for any dates before 1970.

As to why you don't get this same result in every browser, see my oldish blog post JavaScript Date type is horribly broken, which among other things describes that ECMAScript 5.1 and prior required TZ/DST rules to ignore the history of timekeeping and assume the current rule always existed. This was fixed in ECMAScript 6, and in the ECMA Internationalization API - so most modern browsers will give you the correct result.

However, it also depends on where they source their time zone data. Windows computers don't have the full history of the tzdb, unless the browser ships their own copy of it. Browsers that use ICU for this functionality do ship their own copy of the TZDB, so those would have the historical data, but not every browser does this.

Upvotes: 3

Related Questions