Why does adding a space character at the end of a year string cause JavaScript (node) to apply the timezone offset?

Viewed 243

This is in Node v8.9.0 specifically.

Consider these lines:

console.log(new Date("2006"));
console.log(new Date("2006 "));

They produce this output:

2006-01-01T00:00:00.000Z
2006-01-01T08:00:00.000Z

Note that the second line has an 8hr timezone offset.

Why would the presence or absence of a trailing space cause the date to be created with/without the timezone offset?

1 Answers

Summary: The presence of the space causes the date parser to interpret the date as a different format which uses a different assumption for the time zone when there is no timezone specification in the string.

A complication with the Date() constructor or Date.parse() is that with incomplete or partial date strings the parser is trying to guess whether the string should be interpreted as a simplified form of the ISO 8601 format or the RFC2822 format. If it thinks the format is ISO 8601 and no timezone is specified, then the UTC time zone will be assumed. If it thinks the format is RFC2822, then the local computer time zone will be assumed.

So, for your two strings the first is apparently being assumed to be ISO 8601 and thus uses UTC time zone assumption and the second is apparently being assumed to be RFC2822 which uses the local time zone.

The ISO 8601 format that is supported contains no spaces, whereas the RFC2822 format can contain some spaces so it seems likely that the mere presence of the space in the string causes the parser to choose the RFC2822 format which uses the local time zone.

You can read about some of this in the Date.parse() doc on MDN.

For reference here's a piece of the simplified ISO 8601 format:

   Year:
      YYYY (eg 1997)
   Year and month:
      YYYY-MM (eg 1997-07)
   Complete date:
      YYYY-MM-DD (eg 1997-07-16)
   Complete date plus hours and minutes:
      YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
   Complete date plus hours, minutes and seconds:
      YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
   Complete date plus hours, minutes, seconds and a decimal fraction of a
second
      YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
where:

     YYYY = four-digit year
     MM   = two-digit month (01=January, etc.)
     DD   = two-digit day of month (01 through 31)
     hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
     mm   = two digits of minute (00 through 59)
     ss   = two digits of second (00 through 59)
     s    = one or more digits representing a decimal fraction of a second
     TZD  = time zone designator (Z or +hh:mm or -hh:mm)
     T    = a literal T separating the time

You can see that there are no spaces in this format.


Whereas the RFC2822 format contains spaces separate different pieces of the date/time. The full grammar is in the linked RFC, but here's one example where you can see the spaces:

Mon, 25 Dec 1995 13:30:00 GMT

Note that the ES2015 spec for Date.parse() describes the simplified ISO 8601 date format. When you supply any string that does not match that format exactly you probably run into some implementation dependent parsing behavior. Quoting from the ES2015 spec:

the value produced by Date.parse is implementation-dependent when given any String value that does not conform to the Date Time String Format (20.3.1.16)

where that referenced "Date Time String Format" is the simplified ISO 8601 format.

Related