3

How come Javascript Date accepts non-numeric character as year and returns it as 2001?

If you run the following:

new Date('aaaa-05-04');

it results in Fri May 04 2001 00:00:00 GMT+0200. Shouldn't year aaaa result in Invalid Date? You get the same result by setting the year as b, abc or any other combination.

Also setting the month to non-numeric gives a valid date

new Date('aaaa-aa-01');

But not if day is set to 21:

new Date('aaaa-aa-21');

Bonus question:

new Date(1950, 30, 30);

results in Wed Jul 30 1952 00:00:00 GMT+0100

Shouldn't this also result in Invalid Date? Instead it adds to the year.

I'm currently using Chrome 91.

Jimmy Garpehäll
  • 453
  • 5
  • 15
  • There are so many weird date format, and `Date` try to guess one of the many (so doesn't expect "invalid" on many cases). If you want to be more strict, enforce a format (and av. do a check about the format). – Giacomo Catenazzi Jun 04 '21 at 09:00
  • 1
    "aaaa" as the year produces Invalid Date in FF89. For the bonus question, see https://tc39.es/ecma262/#sec-makeday – Teemu Jun 04 '21 at 09:13

3 Answers3

2

This is what's called "undefined behavior". The JavaScript specification says which formats have to be parsed, but if something else comes in, the implementation is free to do other things, including guess if it chooses to not throw an exceptionreturn an invalid Date object (not representing a valid point in time). The various browsers may want to be compatible with things they (or other browsers) have done in previous versions, so they may have ways of guessing that also produces a value for inputs that don't make sense. And it may even be that there is a gap in the specification that allows something weird, and in that case the behavior could be kept for backwards compatibility.

If you want to parse strictly, make sure the input conforms exactly to the format, or use a date parsing library.

(As for the bonus question, adding days at the end of the month or months at the end of a year is a replacement for not having a function to return a new date with added days, etc. This is a defined part of the JavaScript specification.)

Jesper
  • 7,477
  • 4
  • 40
  • 57
  • I really can't make sure that input is correct. That would mean I would have to check if 29 is valid day for february or not for the given year. Then the whole Date object would mean nothing to me as I would already have done all the work. But yeah, using an existing library is probably the way to go. Sad though. – Jimmy Garpehäll Jun 04 '21 at 09:22
  • @JimmyGarpehäll An unfortunate truth. If you don't need something as heavy as moment, I recommend dayjs – Andrew Jun 04 '21 at 09:24
  • 1
    `new Date(year, 1 /* starts at zero because JavaScript is brilliant */, 29).getDate() == 29` can check that. – Jesper Jun 04 '21 at 09:25
  • Yeah. However I would also have to check year and month. It doesn't add that much so might be usable. – Jimmy Garpehäll Jun 04 '21 at 09:35
  • The best solution for parsing dates is using a date parsing library. If you are absolutely convinced that the string is correct and you need to construct a date, that's what the Date constructor is for. – Jesper Jun 04 '21 at 12:19
  • @RobG: you are technically correct (the best kind of correct); updated. – Jesper Jun 07 '21 at 08:21
2

It is not recommended to use the Date parsing mechanism as it is highly implementation dependent, for example while new Date('aaaa-05-04'); will work as you you described in chrome, it will produce invalid date instance in firefox - Before es5 things were even more wild.

The standard specifies that if the format does not match the standard format ( a simplification of ISO 8601), then the implementation might parse based on implementation specific details.

The Date parsing mechanism is beyond fix, this is why tc39 is working on Temporal, a proposal for a new interface for parsing and manupulating dates.

Eventually the only way to tell how Date.parse will work when the passed format does not confirm with the standard format, is to go check the source code of the implementation :)

ehab
  • 7,162
  • 1
  • 25
  • 30
1

How come Javascript Date accepts non-numeric character as year and returns it as 2001? If you run the following: new Date('aaaa-05-04');

Google Chrome will default a Date object to year 2001 when no year is provided

Also setting the month to non-numeric gives a valid date new Date('aaaa-aa-01');

The Date constructor disregards the aaaa-aa part of the string, but when it sees -01 as the first valid part of a date string it makes an assumption this substring must be the MM of a YYYY-MM-DD date string.

But not if day is set to 21: new Date('aaaa-aa-21');

The Date constructor first defaults the YYYY to 2001 and processes the -21 part as the month, resulting in an invalid Date

  • All of the above are guesses based on behaviour unless you've read the source code to determine how the mentioned parsers work. Parsing of strings other than the two formats supported by ECMA-262 is implementation dependent and may produce different results in different implementations and even for different versions of the same implementation. – RobG Jun 06 '21 at 01:35