0

Came across this one tonight and thought I would throw it out there to see if anybody had a rational and clear explanation on what's going on.

I've declared two JavaScript date objects and passed in date strings to the constructor (same date).

In the first variable I have been explicit with the time and added 00:00.

In the second variable I have omitted the time (assuming that it would be midnight).

I've wrapped everything in a Self-Invoking Function but this has no bearing on the outcome.

I'm in GMT so I've used a date that is in BST (GMT+1).

(function() {

  'use strict';

  let a = new Date("2020-06-05 00:00");
  let b = new Date("2020-06-05");

  console.log(a);
  console.log(b);

  console.log(JSON.stringify(a));
  console.log(JSON.stringify(b));

})();

I would have expected Fri Jun 05 2020 00:00:00 GMT+0100 (British Summer Time) on both cases but the second variable without the explicit 00:00 has been set to Fri Jun 05 2020 01:00:00 GMT+0100.

Any explanations?

It appears that a date inside BST (+1) without a time assumes it's +1.

Scenario doesn't happen with new Date("2020-01-05"); for example. This is outside BST and therefore +0.

Fri Jun 05 2020 00:00:00 GMT+0100 (British Summer Time)
Fri Jun 05 2020 01:00:00 GMT+0100 (British Summer Time)
"2020-06-04T23:00:00.000Z"
"2020-06-05T00:00:00.000Z"
Robin Webb
  • 1,355
  • 1
  • 8
  • 15
  • Look at the [`Date()` constructor documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date), in the yellow note under section **3. Timestamp string**: _"Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local."_. So in the first example, your string is considered local. In the second one, it's midnight UTC. And the representation you get of that when doing `console.log(b)` is converted to local (BST), so 1am – blex Jun 19 '20 at 20:36
  • Fantastic @blex. I totally get it now. However, I wonder why string dates passed to Date constructor without times are treated as UTC? More accurately a date without a time will always be midnight. In this case midnight UTC! Just need to remember that this is how it works I guess. Thanks for curing my headache! – Robin Webb Jun 19 '20 at 20:50
  • _"I wonder why"_. You're not alone :) – blex Jun 19 '20 at 20:54
  • 1
    The linked dupe and specifically @drankin2112's answer explains it well. It's mostly a historical thing, and even after several iterations of ECMAScript specs they never quite got it completely "right", and it probably wasn't even possible to. – user120242 Jun 19 '20 at 21:06

1 Answers1

2

Due to the ECMA specs:

ECMA-262 Date(value) constructor specs
Date.parse

If the String conforms to the Date Time String Format, substitute values take the place of absent format elements. When the MM or DD elements are absent, "01" is used. When the HH, mm, or ss elements are absent, "00" is used. When the sss element is absent, "000" is used. When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.

According to ECMA specs:

  • Date only forms without timezone are interpreted as UTC.
  • Date-Time without timezone are interpreted as local time.

Generally you are better off just using the full ISO-like form with timezone attached. But since these are spec-compliant, if you always keep it under control it's safe to depend on this behavior, albeit it might get confusing sometimes for both you and others, especially when it comes to server-side code and DB storage.

user120242
  • 14,918
  • 3
  • 38
  • 52