The result is incorrect due to the consideration of the date as UTC:
This issue stemmed from a mistake in the ES5 specification, which stated that no timezone indicator meant UTC, contrary to the ISO-8601 standard it was supposed to adhere to. ES2015 rectified this by defining that no timezone indicator implied local time (in alignment with ISO-8601), but this would have caused compatibility issues when used on strings containing dates only (like "2018-01-17"
). Subsequently, ES2016 made further adjustments, leading to stability since then. In cases where there is no timezone indicator:
- A date-only string (e.g.,
"2019-05-20"
) is parsed in UTC
- A date/time string (e.g.,
"2019-05-20T10:00"
) is parsed in local time
Due to these specification inconsistencies, various JavaScript engines initially exhibited behaviors aligned with old specifications (ES5), ES2015, or ES2016. Notably, iOS continues to maintain an incorrect behavior.
As of May 20th, 2019, the situation is as follows:
- Desktop versions of Chrome, Firefox, Edge, and even IE11 all correctly adhere to the ES2016+ specification.
- Safari (on desktop or iOS) erroneously parses date/time strings without timezone indicators as UTC.
- All current iOS browsers (including Safari, Chrome, Firefox, Brave, Dolphin...) also parse date/time strings without timezone indicators as UTC due to the use of JavaScriptCore (JSC) on iOS. The limitation arises because non-Apple iOS applications cannot allocate executable memory for other optimizing engines like V8 or SpiderMonkey, hence resorting to JSC. (Chrome's V8 may transition away from JSC towards a "JIT-less" interpreter.)
You can verify your browser's behavior through the following code snippet:
var may20 = new Date("2019-05-20");
// If parsed in UTC, UTC hours should be 0
console.log(may20.getUTCHours() === 0 ? "OK:" : "Error:", may20.toLocaleString());
var may20At10 = new Date("2019-05-20T10:00");
// If parsed in local time, local hours should be 10
console.log(may20At10.getHours() === 10 ? "OK:" : "Error:", may20At10.toLocaleString());
(The accuracy of this check depends on the differentiation between UTC and local time on May 20th, 2019. It works in regions like the UK [GMT+0100] or New York [not on GMT], but not in locations observing GMT year-round like Timbuktu.)
Note, Safari does not support this without the T.
Indeed, the only mandatory date/time format supported by JavaScript engines is the ISO-8601 subset defined here (along with the output of toString
, albeit its specifics are unspecified). Current observations as of May 20th, 2019, indicate Safari's deviation from this specification.
However, isn't there a more elegant solution compatible across different browsers?
The process may seem complex, but that's the necessary mechanism within the Date
constructor. By incorporating it into your standard library, you ensure seamless functionality.