4

While debugging my application I found weird thing:

new Date('2017-5-19')  -> Fri May 19 2017 00:00:00 GMT+0300 (FLE Summer Time)
new Date('2017-05-19') -> Fri May 19 2017 03:00:00 GMT+0300 (FLE Summer Time)

I set date from String, like '2017-5-19', but when there is zero before month number, date is different than without zero.

How can I achieve the same result by both 5 and 05 inputs?

p.s. I have to support strict mode

Vladyslav K
  • 2,178
  • 3
  • 19
  • 25
  • 1
    According to the existing logic for dates, it seems that if you defy the format which it is expecting it does not convert the value from your utc to your local timezone. So '2017-05-19' being the correct format 'yyyy-mm-dd' converts to your local timezone. Does this help? – Pansul Bhatt Apr 19 '17 at 10:15
  • @PansulBhatt—according to [*ECMA–262*](http://www.ecma-international.org/ecma-262/7.0/index.html#sec-date-time-string-format), a date in the format YYYY-MM-DD should be treated as UTC, not local (but of course not all browsers in use do that). – RobG Apr 19 '17 at 22:45

1 Answers1

4

As indicated on MDN, using the Date constructor to parse dates is discouraged because of implementation differences.

However, if you really want to do so, the only solution is to ensure that the inputs you provide are consistent. This will ensure that (at least within a single environment) the outputs will be consistent.

To have both work like 2017-5-19:

function adjustDateString(str) {
    return str.split('-').map(Number).join('-');
}

console.log(new Date(adjustDateString('2017-5-19')))
console.log(new Date(adjustDateString('2017-05-19')))

To have both work like 2017-05-19:

function padTo2Digits(str) {
    return str.length >= 2 ? str : '0' + str;
}

function adjustDateString(str) {
    return str.split('-').map(padTo2Digits).join('-');
}

console.log(new Date(adjustDateString('2017-5-19')))
console.log(new Date(adjustDateString('2017-05-19')))

Edit: However, you're probably better off, as I pointed out above, not using the Date constructor on a string. Just split it into its values and pass those into the constructor:

function parseDate(str) {
  var parts = str.split('-').map(Number);

  return new Date(parts[0], parts[1], parts[2]);
}

console.log(parseDate('2017-5-19'));
console.log(parseDate('2017-05-19'));

Using array deconstructuring syntax (requires ES6+):

function parseDate(str) {
  let [year, month, day] = str.split('-').map(Number);

  return new Date(year, month, day);
}

console.log(parseDate('2017-5-19'));
console.log(parseDate('2017-05-19'));
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Still trying to work out the logic of parsing a string to values, then creating another string for another parser to parse. Why not parse it **once** and give the values directly to the Date constructor? Note your first sentence: "*using the Date constructor to parse dates is discouraged*". ;-) – RobG Apr 19 '17 at 22:45
  • @RobG Fair point. I've added an addendum. – JLRishe Apr 20 '17 at 03:51