new Date("0001-01-01T01:00:00Z")
--> Mon Jan 01 0001 02:50:16 GMT+0150 (Moscow Standard Time)
Incorrect GMT: my timezone GMT+3000
, but date creates GMT+0150

- 21,465
- 8
- 65
- 74

- 11
- 2
-
The "GMT+0150" is a display issue with the toString() method (or when you just do a `console.log` in your browser). The internal datetime reprentation is the same for javascript. – Pac0 Jan 31 '19 at 13:28
-
Possible duplicate of [Convert date to another timezone in JavaScript](https://stackoverflow.com/questions/10087819/convert-date-to-another-timezone-in-javascript) – Pac0 Jan 31 '19 at 13:29
-
The "GMT+0150" is't a display issue, because getTimezoneOffset() returns incorrect value – Lina Gurinovich Jan 31 '19 at 13:32
-
Since you haven't provided an explicit timezone, the timezone offset is inferred by your locale settings. (note: the date in javascript are notoriously hard to work with, especially with these timezones / offset problems) – Pac0 Jan 31 '19 at 13:34
-
1I really doubt any country on earth had time zones already in the year 1 A.D., so I wonder what’s the point of this exercise anyway …? Bet you get a different result if you start this with something like `new Date("2001-…` – 04FS Jan 31 '19 at 13:38
-
@04FS Indeed, I used 1990 year in my example. Note that there are somehow retroactive definitions for IANA timezones / offsets for those years, but they might not make sense depending on the application. For instance, Asia/Jerusalem will give me an offset of +2:20:41, probably set as a "default value" by IANA rules and inferred by the position of the sun, but I'm just guessing at this point. – Pac0 Jan 31 '19 at 13:40
-
If you need to rely on `getTimezoneOffset()`, I think it would be better to reformulate your question with the actual goal you are trying to achieve. It will enable other answers maybe more useful for your actual usecase. – Pac0 Jan 31 '19 at 13:47
-
https://bugs.chromium.org/p/chromium/issues/detail?id=849404 – Johan Karlsson Jan 31 '19 at 13:47
-
@LinaGurinovich About the 16 seconds, I added something about that to my answer. This is not a problem of parsing, again, only of timezone offset "definitions" for those years. When some committee normalized timezone, this was about recently. They tried to establish some rules to get something meaningful (kinda) for the previous years. Basically, they used some calculations depending on solar time, which is why it doesn't give nice round numbers. This is all fixed convention, and it may or may not fit your application. Do you actually need those 0001 years ? – Pac0 Jan 31 '19 at 14:00
-
for additional advice, I recommend that you give an eye on the widely uses "moment.js" library. (But it is good to know about the "pure JS" date system, of course) – Pac0 Jan 31 '19 at 14:03
3 Answers
For dates, you can (and should, in my opinion) define them in UTC ISO 8601 "Z" format ("YYYY-MM-DDTHH:MM:SSZ"), just as you did.
However, to get a user-friendly string representation of those dates, it will depend on your client and on the Javascript engine used. You can constrain the output if you explicitly specify a reference timezone with toLocaleString()
.
var date = new Date("1990-01-01T01:00:00Z");
console.log(date.toLocaleString("en-US", {timeZone: "Asia/Jerusalem"}));
console.log(date.toLocaleString("en-US", {timeZone: "Europe/Moscow"}));
console.log(date.toLocaleString("en-US", {timeZone: "Africa/Djibouti"}));
// output on my machine, should be the same on yours :
// 1/1/1990, 3:00:00 AM
// 1/1/1990, 4:00:00 AM
// 1/1/1990, 4:00:00 AM
console.log(date.toString());
// output **on my machine**, should **not** be the same on yours
// Mon Jan 01 1990 02:00:00 GMT+0100 (Central European Standard Time)
For the 16 seconds issue, this is linked to the way offset are defined by the rules for those dates before the notion of IANA timezone existed.
They probably don't make sense in your application, and I discourage you to use dates like 1st January of year 0001 for your examples.
Examples :
var date = new Date("0001-01-01T01:00:00Z");
console.log(date.toLocaleString("en-US", {timeZone: "Asia/Jerusalem"}));
console.log(date.toLocaleString("en-US", {timeZone: "Europe/Moscow"}));
console.log(date.toLocaleString("en-US", {timeZone: "Africa/Djibouti"}));
// output on my machine, should be the same on yours :
// 1/1/1, 3:20:54 AM
// 1/1/1, 3:30:17 AM
// 1/1/1, 3:27:16 AM
console.log(date.toString());
// output **on my machine**, should **not** be the same on yours
// Mon Jan 01 0001 01:09:21 GMT+0009 (Central European Standard Time)
More information here (thanks Johan Karlsson for the link) :
https://bugs.chromium.org/p/chromium/issues/detail?id=849404
The most relevant comment from this link is, I think :
This is working as intended and working per spec. The spec says that we have to follow the IANA timezone database.
In 1880, there's no standard timezone and America/Los_Angeles timezone offset was based on its longitude. The same is true of other timezones.
Also note that there are many timezone around the world the zone offset (and whether or not to have DST or when to start DST) have changed multiple times even since 2000 (e.g. Europe/Moscow). The change to make them work correctly also brought in what's reported here.

- 21,465
- 8
- 65
- 74
-
added a bit more info, from the link Johan Karlsson gave on comments on your question. – Pac0 Jan 31 '19 at 14:18
Pac0's answer is correct (and you should accept that answer since it came first, not this one). But just to provide a detailed explanation:
Dates from before recorded history of time zones are marked in the time zone database as LMT
- which stands for Local Mean Time. The offsets are derived from the latitude and longitude of the city, not by any current political determination.
Since the offset shown is 1:50:16
ahead of UTC, I can derive that your system time zone is Europe/Minsk
. This is seen in the tzdb sources here:
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Minsk 1:50:16 - LMT 1880
This is just the first line of the zone entry for Europe/Minsk
, which says that until 1880, use the LMT entry of UTC+1:50:16.
As to why it says "Moscow Standard Time" - that string comes from the Unicode CLDR data, which in the /common/supplemental/metaZones.xml
file we can see:
<timezone type="Europe/Minsk">
<usesMetazone to="1991-03-30 23:00" mzone="Moscow"/>
<usesMetazone to="2011-03-27 00:00" from="1991-03-30 23:00" mzone="Europe_Eastern"/>
<usesMetazone to="2014-10-26 22:00" from="2011-03-27 00:00" mzone="Europe_Further_Eastern"/>
<usesMetazone from="2014-10-26 22:00" mzone="Moscow"/>
</timezone>
So Europe/Minsk
uses the Moscow
metazone up until 1991. Then, using one of the language files such as /common/main/en.xml
for English, we can see the actual text assigned to this metazone:
<metazone type="Moscow">
<long>
<generic>Moscow Time</generic>
<standard>Moscow Standard Time</standard>
<daylight>Moscow Summer Time</daylight>
</long>
</metazone>
And now you have a complete picture for how the string Mon Jan 01 0001 02:50:16 GMT+0150 (Moscow Standard Time)
was derived from 0001-01-01T01:00:00Z
.

- 230,703
- 74
- 448
- 575
A timezone is an offset plus a date range. To format your date, javascript wants to know what the timezone offset was for Moscow in the year zero. This is hard information to come by, and might not be accurate ! You think you're asking something simple, but it's actually pretty extreme. If you want to use the date object to represent durations, you should take the epoch as your starting point.

- 27,056
- 15
- 80
- 110
-
Right. But even at epoch, you could be surprised as some countries have changed offset or Daylight Saving Time rules since then. For instance, to take an example related to OP's question, Russia has stopped using DST since 2010. Dates in summer won't have same UTC offset before 2010 or after. – Pac0 Jan 31 '19 at 16:33