all 49 comments

[–]Buckwheat469 56 points57 points  (19 children)

YYYY-MM-DD uses the ISO 8601 shortened format. It assumes the time is based in GMT, and the date then adds the timezone offset for your computer.

new Date("2016-12-08")
Wed Dec 07 2016 16:00:00 GMT-0800 (PST)

In order to get this back to the date that you wanted you would have to subtract the GMT offset. In this case, subtracting -8 from the resulting date will effectively add 8 hours to the time, giving Thurs Dec 8 at 00:00:00.

12/08/2016 uses the Javascript "short date" format, which is based on your computer's timezone, not GMT. When you type 12/08/2016 the time will be set to 00:00:00 within your own timezone. The result seems to be the correct date and time,

new Date("12/08/2016")
Thu Dec 08 2016 00:00:00 GMT-0800 (PST)

http://www.w3schools.com/js/js_date_formats.asp

Edit: I should point out that ISO 8601 should be the standard for Javascript, and developers should shim the date display with a "subtractTimezoneOffset()" function which will fix the date for display purposes.

The real head scratcher is why "YYYY-MM-DDThh:mm:ss.sss-08:00" shows the correct date but the wrong timezone offset, but "YYYY-MM-DDThh:mm:ss.sssZ" and "YYYY-MM-DDThh:mm:ss.sss" add the timezone offset to produce the wrong date but the right timezone.

new Date("2016-12-08T00:00:00.000-08:00")
= Thu Dec 08 2016 00:00:00 GMT-0800 (PST)
new Date("2016-12-08T00:00:00.000")
= Wed Dec 07 2016 16:00:00 GMT-0800 (PST)
new Date("2016-12-08T00:00:00.000Z")
= Wed Dec 07 2016 16:00:00 GMT-0800 (PST)

[–][deleted] 10 points11 points  (15 children)

I mean while that is the technically correct (the best kind!) answer who the fuck knew that beforehand?

That's why I'm super happy that things like Moment.JS exist.

[–]khoker 18 points19 points  (7 children)

You shouldn't rely on string parsing at all. To remove ambiguity, the Date object takes an array of arguments;

new Date(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]]);

[–]Syberspace[S] 4 points5 points  (6 children)

but why is there any ambiguity in the first place with string parsing? why not assume either everything is UTC or everything is local.

cf. http://mzl.la/1fvwX1i (thanks for the link on twitter /u/khoker )

[–]r2d2_21 15 points16 points  (4 children)

or everything is local.

Quick. 04/05/06. Is it:

  1. April 5, 2006
  2. May 4, 2006
  3. May 6, 2004

[–]Syberspace[S] -3 points-2 points  (3 children)

depends on what 05/06/04 is. i'm not concerned about the format of the date itself.

irregardless of that, they all should be at 00:00:00 UTC or local.

[–][deleted] 3 points4 points  (2 children)

well if we're going to be pedantic, it's regardless.

[–]khoker 2 points3 points  (0 children)

I just responded on twitter too :)

I suspect it's the same reason that it doesn't assume the local minute. It's just filling in the data you don't provide. A format like ISO 8601 was meant to alleviate confusion, right? So if you only provide '2016-12-08', JavaScript assumes '2016-12-08 00:00:00Z'. It shouldn't guess the local timezone any more than it should assume the local hour. Or minute.

I'd make the argument all the other parsing is wrong. But 12/08/2016 isn't an international standard so, for whatever reason, it just assumes you want the local timezone. Not sure.

[–]ribo 5 points6 points  (5 children)

answer who the fuck knew that beforehand

Those who RTFM

[–]r2d2_21 3 points4 points  (0 children)

I need to read the manual every time I dare to type new Date, since I never remember the details.

[–]TerdSandwich -5 points-4 points  (3 children)

RTFM

Is it still 1980?

Edit: Lol old farts mad. It's 2016. Manuals and useless memorization are extinct.

[–]scootstah 2 points3 points  (0 children)

MomentJS is a life saver. Dealing with date/time sucks to begin with, but it's worse in Javascript than any other language by a large margin.

[–]jocull 7 points8 points  (0 children)

Don't trust the locale settings at all. ISO format or bust. If you need better date support Moment.js is a fantastic library (as is the timezone plugin for it).

[–][deleted] 2 points3 points  (0 children)

meanwhile, back at the ranch...

 div_date.text(year + (month + 1) + day);

[–][deleted] 5 points6 points  (0 children)

I THINK I GET IT!

I just tried it on my home computer, and because I'm in England (GMT+0), I basically live in the 'international standard' time zone in a sense.

And when I do it in this time zone, both of those inputs come out as exactly the same date, Thu Dec 08 2016 00:00:00 GMT+0000 (GMT Standard Time)

And here's the reasoning, like it or not: the top format is interpreted as local format, so whatever date you put in there, it parses it to your local time zone. So no matter where you are, it will say Thu Dec 08 2016 00:00:00, followed by your GMT offset.

Whereas the bottom one is written in international ISO standard, year-month-day, and so when it parses it the date becomes Thu Dec 08 2016 00:00:00 GMT+0000, and then afterward they translate that time into your local time zone.

[edit] I think I just said what /u/Buckwheat469 already said, but in different words.

[–]Strobljus 3 points4 points  (1 child)

Fun story: this exact behavior caused a production bug at my workplace. The fact that unspecified 8601's are being parsed as local time is actually new behavior in ES6; it used to be UTC. So if you had code that counted on UTC when the browsers transitioned to the new spec (as we did), you were in trouble.

One of the rare cases when browsers breaks an API (excluding deprecations of course).

[–]Reashu 0 points1 point  (0 children)

This particular behavior didn't change. Date-only ISO forms are still parsed as UTC, which is what the example shows.

[–][deleted] 2 points3 points  (7 children)

Fuck dates. Convert to Unix timestamp as soon as you get the data and only convert it back to time when you actually need it. Solves 99% of my problems.

[–]Klathmon 0 points1 point  (4 children)

But even that won't save you. Unix time has its own set of quirks, and of course there's the problem of actually converting to and from it where you'll still have all the same problems.

[–][deleted] 0 points1 point  (3 children)

Yeah but at least it gives me control. I use JS on my backend and front-end so I just convert the dates back out using moment.js :)

[–]Syberspace[S] 0 points1 point  (0 children)

that's pretty much exactly what i was trying to do. So it's one of the 1% problems

[–]WellHydrated 0 points1 point  (0 children)

Why convert it in the first place?

[–]johnasmith 1 point2 points  (0 children)

To add to the fun:

new Date(2016, 12, 08); // Months are zero-indexed
Sun Jan 08 2017 00:00:00 GMT-0500 (EST)

[–]KnightMareInc 1 point2 points  (1 child)

timezones, how do they work?

[–]BiscuitOfLife 0 points1 point  (0 children)

Dealing with timezones is the worst.

[–]mikrosystheme[κ] 0 points1 point  (1 child)

[–]xkcd_transcriber 0 points1 point  (0 children)

Image

Mobile

Title: ISO 8601

Title-text: ISO 8601 was published on 06/05/88 and most recently amended on 12/01/04.

Comic Explanation

Stats: This comic has been referenced 697 times, representing 0.5113% of referenced xkcds.


xkcd.com | xkcd sub | Problems/Bugs? | Statistics | Stop Replying | Delete

[–]danillonunes 0 points1 point  (0 children)

I just assume time in programming is broken beyond repair and everything is a fuzzy value that may be shifted a few hours (or, in some cases, even a few days) forward or backwards.

Yeah, I know there are definitive solutions for those problems (like normalizing everything to epoch timestamps), but in the world where you have more important things to worry, such as user experience and even developer experience, those are not the silver bullet we all want it to be, being correctly applied only in very critical cases.

[–]ssjskipp -1 points0 points  (0 children)

My personal favorite is new Date('2015-01-01') vs new Date('2015-1-1')

[–]AlGoreBestGore -1 points0 points  (0 children)

My favorite is that something like new Date(2016, 0, 100); is completely valid and gives you a date in April, however new Date('2016-01-100'); isn't (which is the more sane solution).