Where does GMT-0456 Timezone Come From?

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. Since 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)"

One problem is that, the year zero should not exist, but it's understandable that JavaScript has not been invented around that time. What really puzzles me is, why does the timezone show up as GMT-0456, instead of the usual GMT-0500?

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.

Since I was testing on Chrome browser, I started with the V8 JavaScript engine. 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. In the 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.