How a date string is interpreted by javascript depends on the browser vendor and version (reference). To get a reliable result across browsers in Elm, use
Date.fromString("2018-01-06T00:00:00Z")
(Also note that the Date type in Elm represents a moment in time, not a day on the calendar, so depending on what you’re doing with dates, you may want to instead use a data type like { year : Int, month : Int, day : Int } instead of Date.)
I see the same result in JS as in Elm in the browser:
> new Date("2018-01-06")
Sat Jan 06 2018 01:00:00 GMT+0100 (CET)
> new Date("2018-01-06").toString()
"Sat Jan 06 2018 01:00:00 GMT+0100 (CET)"
And I don’t even get the same result as you in node (see how it morphs it into the fifth), if you call .toString() you see it with the time zone:
> new Date("2018/01/06")
2018-01-05T23:00:00.000Z
> new Date("2018/01/06").toString()
'Sat Jan 06 2018 00:00:00 GMT+0100 (CET)'
Seems like there is some sort of inconsistency between Node.js and browser environments (I tested in Chrome 63 and Node v9.3.0). So, no, JS didn’t get it right really
Which Node.js version did you use that has a Date constructor that doesn’t take the locale timezone into account?
The ISO8601 standard says that dates without timezone indicators are to be treated as being in the local timezone. The JavaScript standard is the same as ISO8601 with respect to format but interprets dates without timezone indicators as being in UTC. So, what you are seeing is the conversion of a timezone-less date into UTC and then into the local timezone.
I wrote code recently to deal with this but I had to break out of Elm to do it because it didn’t expose the JavaScript getTimezoneOffset method for dates. And since I needed to access this from within a decoder, I had to write it as a native module for Elm.
To be fair, you don’t have to break out of Elm to do this in 0.18. I have a Date.Extra library that exposes an offsetFromUtc function by taking advantage of Date part extractions being given as local time and Date.toTime being given as UTC.
If the goal is decoding ISO 8601 date strings correctly, the library also has a fromIsoString function (which interprets dates without time offset as representations of local time).
Nice module. Much nicer than the other date extension module I had seen. Your approach to recovering the offset feels like a big work around for the underlying JavaScript function not being exposed, but it works. Your logic for figuring out the local offset for a given date looks essentially like mine — i.e., try to find the fixed point of a function and recognize that we can end up with an oscillation in some cases.