1

I am wondering why I have an incorrect timezone for old dates in JS output.

I've been experimenting with JavaScript's Date object and have encountered an issue when using the years before 1900 and different timezone offsets. It seems the output doesn't match the expected date and time. Here's an example:

const dateStr = "1701-01-01T00:00:00+00:00";
const date = new Date(dateStr);
console.log(date.toString());

// OUTPUT: VM567:3 Fri Dec 31 1700 23:45:16 GMT-0014 (Central European Standard Time)

I was expecting the output to be "1701-01-01T00:00:00.000Z", but instead, I got "Fri Dec 31 1700 23:45:16 GMT-0014 (Central European Standard Time)".

I've searched online and tried using ChatGPT, but couldn't find a satisfactory explanation for this behavior. Could someone please provide a link to the relevant specification or offer an explanation for why the output is different from what I expected?


Screenshots:

GMT+0:00,GMT+1:00

GMT+2:00

GMT+0:00,GMT+1:00

dragomirik
  • 612
  • 2
  • 6
  • 13
  • 1
    The format produced by *Date.prototype.toString* is [specified in ECMA-262](https://262.ecma-international.org/#sec-date.prototype.tostring). If you were expecting the same format as the input string (nominally ISO 8601), use [*toISOString*](https://262.ecma-international.org/#sec-date.prototype.toisostring). – RobG Apr 20 '23 at 13:12
  • 1
    Regarding the unusual offset, see [*Browsers, time zones, Chrome 67 Error (historic timezone changes)*](https://stackoverflow.com/questions/50609860/browsers-time-zones-chrome-67-error-historic-timezone-changes). – RobG Apr 20 '23 at 13:14

1 Answers1

1

The strange offsets you're encountering for historic dates represent the calculated Local Mean Time at the the coordinates specified in the zone.tab or zone1970.tab files in the tz database.

For example, GMT+0202 is likely coming from the LMT value for Europe/Kyiv, which is calculated to be 2:02:04

The complete record for this zone (as of 2023c) is:

# Zone  NAME         STDOFF   RULES  FORMAT  [UNTIL]
Zone    Europe/Kyiv  2:02:04  -      LMT     1880
                     2:02:04  -      KMT     1924 May  2 # Kyiv Mean Time
                     2:00     -      EET     1930 Jun 21
                     3:00     -      MSK     1941 Sep 20
                     1:00     C-Eur  CE%sT   1943 Nov  6
                     3:00     Russia MSK/MSD 1990 Jul  1  2:00
                     2:00     1:00   EEST    1991 Sep 29  3:00
                     2:00     C-Eur  EE%sT   1996 May 13
                     2:00     EU     EE%sT

This is saying that before 1880, all we know about this zone is its local mean time. There was no concept of time zone in the region. The same offset can start to be called KMT (Kyiv Mean Time) after 1880. Only starting 1924-05-02 can it start to be called EET and use a +02:00 offset. The explanations for these dates can be found in commentary in the source file.

The location chosen to calculate the LMT value is based on the coordinates in the zone1970.tab file, which are +5026+03031, which is the ISO 6709 (DMS) formatted equivalent of 50° 26′ N, 30° 31′ E, the approximate geographic location of Kyiv, Ukraine.

LMT is the way that the TZDB reconciles our modern concept of time zones with historical dates which had no such concept.

You will see the effect of this in any implementation that relies on the TZDB for determining time zone offsets, including JavaScript in most modern browsers.

Note, the 4 seconds in the offset 2:02:04 are being truncated. This is relatively common, because all modern offsets can be expressed in terms of hours and minutes only.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575