Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Date('2015-1-1') outputs different from Date(2015-01-01)

I just found that if I use new Date('2015-1-1'), the time is no timezone effect, but If I use new Date('2015-01-01') the time has timezone effect in Node.js.

I output 4 Date():

    console.log(new Date('2015-1-1'));
    console.log(new Date('2015-01-1'));
    console.log(new Date('2015-1-01'));
    console.log(new Date('2015-01-01'));

the output is

Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 08:00:00 GMT+0800 (CST)

you can see the last time is 08:00:00 because I'm in +8 timezone.

I think the output depends on the digit of the month or date number. When it's 10, 11 or 12 the output is always 08:00:00

I'm wondering why and if there is a better way to handle this except manually check the bit of month and date number?

like image 266
Brick Yang Avatar asked Nov 29 '15 11:11

Brick Yang


1 Answers

Up to and including ECMA-262 ed 3, parsing of date strings was entirely implementation dependent. With ES5, ISO 8601 format strings without a timezone were to be parsed as UTC, however parsing any other type of date string is still implementation dependent.

With ECMAScript 2015, such strings without a timezone are to be parsed as local (i.e. with an offset based on system settings).

So it would seem that your Node.js implementation does not recognise the first 3 strings as ISO 8601 and so parses them according to some other internal logic that treats them as UTC.

The last string is seen as ISO 8601 compliant and so is parsed as local.

If you wish to parse all such strings as local, you can use a simple function like:

/*  @param {string} s - date string in format yyyy-[m]m-[d]d
**  @returns {Date} - a Date object for the specified date in a
**  timezone based on system settings.
**  Assumes that the string is a valid date.
*/
function parseISOLocal (s) {
  var b = s.split(/\D/);
  return new Date(b[0], b[1]-1, b[2]);
}

document.write(parseISOLocal('2015-1-1'))
like image 150
RobG Avatar answered Sep 23 '22 02:09

RobG