Recently, someone on the DCTech Slack community asked why the
Date.prototype.toDateString function is having an off-by-one error:
new Date("2020-10-17").toDateString(); "Fri Oct 16 2020"
My immediate response was: timezone.
The group then proceeded to discover that the
Date constructor would interpret a date-only string as being in UTC timezone.
Washington, DC uses Eastern Daylight Time that is four hours behind UTC, so the timezone of the constructed
Date object is 20:00:00 local time on the previous date.
toDateString uses local time, it prints as the previous date.
After that, I started testing some boundary conditions:
new Date("0001-01-01").toString() "Sun Dec 31 0000 19:03:58 GMT-0456 (Eastern Standard Time)" new Date("0000-01-01").toString() "Fri Dec 31 -0001 19:03:58 GMT-0456 (Eastern Standard Time)"
I did a binary search to find when did the timezone change from GMT-0456 to GMT-0500:
new Date("1883-11-18 12:03:57").toString(); "Sun Nov 18 1883 12:03:57 GMT-0456 (Eastern Standard Time)" new Date("1883-11-18 12:03:58").toString(); "Sun Nov 18 1883 12:03:58 GMT-0500 (Eastern Standard Time)"
The magic timestamp turns out to be between 1883-11-18 12:03:57 and 1883-11-18 12:03:58. Something must have happened on that day!
An Internet search of the date turned up this article: Today in History: November 18, 1883: Time zones standardized in Canada and USA. Basically,
- Until 1883-11-18, each town sets its own time, based on their own estimation of solar time.
- Having different local time in each town was causing problems with the railroads, so that the railroad companies established five timezones for Canada and the United States.
- 1883-11-18 marks the date when Eastern Standard Time was established.
This explains the date 1883-11-18, but still doesn't explain why the cut-off time was 12:03:57 and why the previous timezone is GMT-0456. I started looking for answers in the computer source code.
I located the code related to
Date and timezone, but didn't find GMT-0456 in there.
Instead, V8 invokes
GetLocalOffsetFromOS function, suggesting that the timezone information comes from the operating system.
I don't have access to Windows source code, but I recall that Linux uses tzdata for timezone information.
I downloaded the current Time Zone Database.
northamerica data file, I found the following records:
# US eastern time, represented by New York # From Paul Eggert (2014-09-06): # Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208 # says that New York City Hall time was 3 minutes 58.4 seconds fast of # Eastern time (i.e., -4:56:01.6) just before the 1883 switch. Round to the # nearest second. # Rule NAME FROM TO - IN ON AT SAVE LETTER Rule NYC 1920 only - Mar lastSun 2:00 1:00 D Rule NYC 1920 only - Oct lastSun 2:00 0 S Rule NYC 1921 1966 - Apr lastSun 2:00 1:00 D Rule NYC 1921 1954 - Sep lastSun 2:00 0 S Rule NYC 1955 1966 - Oct lastSun 2:00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58 -5:00 US E%sT 1920 -5:00 NYC E%sT 1942 -5:00 US E%sT 1946 -5:00 NYC E%sT 1967 -5:00 US E%sT
So the answer to this GMT-0456 mystery is:
- Eastern Time is really "time in New York".
- Before Eastern Standard Time was established on the noon of Nov 18, 1883, the local time in New York was 12:03:58.
- That time was 4 hours and 56 minutes (04:56) behind Greenwich Mean Time, so that it shows up as GMT-0456.