8

It seems to me that Date.parse assumes all months have 31 days. Including months with 30 days and including February(which should only ever have 28/29 days).

I checked this question 31 days in February in Date object

But the answer there suggested there was nothing wrong with Date in his issue..Somebody said something to the questioner about zero indexing and he pretty much said "oh ok", and determined that it was his mistake and not a mistake of Date.

Another question Date is considering 31 days of month the guy was doing some subtraction was a number of lines of code and he seemed to not put the error down to Date in the end.

But this example that I have seems to be a bit different and more clear cut. It involves Date.parse and can be demonstrated with one/two lines of code.

Date.parse is aware that there are not 32 days in a month, that's good

Date.parse("2000-01-32");
NaN

But In February it thinks there can be 30 or 31 days

Date.parse("2013-02-30");
1362182400000

Date.parse("2013-02-31");
1362268800000

In fact it looks like it thinks all months have 31 days. That is really strange for a method that is meant to parse a date.

And there's no issue of zero indexing here. As Date.parse("...") doesn't use zero indexing (And even if it did, it wouldn't cause it tot make the error of thinking there are 31 days in February - that is more than one off!

Date.parse("01-00-2000");
NaN

Date.parse("00-01-2000");
NaN
Community
  • 1
  • 1
barlop
  • 12,887
  • 8
  • 80
  • 109
  • Good point. In fact, `new Date("2013-02-31")` for me returns a date representing `Sun Mar 03 2013` whereas `Date.parse("2013-02-32")` returns *Invalid Date* – CodingIntrigue Aug 29 '15 at 10:49
  • @RGraham well, re your new Date example, some would say that's not an error 'cos it's adding and that's why I used Date.parse as my example. And re Date.parse with a date of 32, as I say, it knows there aren't 32 days in any month. But it messes up in its assumption that all months have 31 days. – barlop Aug 29 '15 at 10:54
  • 2
    `new Date` uses `Date.parse` under the hood. I think it's because Date.parse in ES5 strictly follows the [ISO 8601 date format](http://www.w3.org/TR/NOTE-datetime) which doesn't specify any restrictions on days of the month. Same as it parses `2015-06-31` just fine – CodingIntrigue Aug 29 '15 at 10:56
  • I guess Date.parse is adding too then, though it's just even more wrong looking when it does that 'cos one expects a parsing method to only parse correct dates. – barlop Aug 29 '15 at 11:00
  • `Date.parse` doesn't make any assumptions, it just follows the rules of ISO 8601. And one rule is that the day can be a value between 01 and 31. Moreover `Date.parse` doesn't create a date but calculates the milliseconds since 1.1.1970. So the result may be disturbing but it's not completely unreasonable. – a better oliver Aug 29 '15 at 11:05
  • @zeroflagL well it is rather unreasonable to accept a standard that allows invalid dates like 31st feb (And as per incorrect standard, allowing dates that are only invalid within limits e.g. yes to 31st of feb but no to 40th feb) – barlop Aug 29 '15 at 11:14
  • Ok, javascript accepts 1-31 as dates, regardless of the month as other programming languages do too. Either take or leave... – Pavel Gatnar Aug 29 '15 at 11:32
  • That's nothing a format is concerned with. That would actually be the responsibility of `Date.parse` ;) Valid format (=plausible value) and valid value are two different things. Try to think of it this way: There's no if in format. – a better oliver Aug 29 '15 at 11:48
  • @zeroflagL Well, as I said in my earlier comments on your answer. If the writers of the ISO standard were labouring under a restriction of having no IF, because they are defining a "format", and a "format" allows them to specify a number range but perhaps doesn't let them say that a number range is conditional on another number range, then they should fix eg Feb, and not call their standard a "format". And I think it's a stretch to say that they were allowed in the standard to rule out "illegal element values" but they weren't allowed to specify illegal element values in the standard. – barlop Aug 29 '15 at 11:53

3 Answers3

3

According to the specification for Date.parse() (emphasis mine):

The function first attempts to parse the format of the String according to the rules called out in Date Time String Format. […] Unrecognisable Strings or dates containing illegal element values in the format String shall cause Date.parse to return NaN.

And according to the specification for Date Time String Format (emphasis mine):

ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ

Where the fields are as follows: […] DDis the day of the month from 01 to 31.

Therefore, any date with a day of month greater than 31 is illegal and Date.parse() returns NaN.

Please notice that the standard defines a date format, not a date: the static method isn't required to make additional verifications, and everything else is implementation-specific. For instance, Date.parse('2013-02-30') and Date.parse('2013-04-31') both return NaN on Firefox.

Blackhole
  • 20,129
  • 7
  • 70
  • 68
  • Then the ISO standard for how to define a Date, allows invalid dates like 31st february, so the ISO standard is wrong. – barlop Aug 29 '15 at 11:11
  • @barlop The standard don't define a date, it defines a date format. That's a huge difference. I've added information in my answer, by the way. – Blackhole Aug 29 '15 at 11:15
  • So when defining/writing a "format" you can specify a range but can't specify that a range is dependent on another range?! Is there a definition of format that specifies that limitation? If so then they should remove that inflexibility by not calling it a format, and by ensuring that only valid dates are accepted in their standard. – barlop Aug 29 '15 at 11:18
  • @barlop That's the how the specification is written, anyway. We can't do a lot about it. Does it answer your question, or do you want a method to check that the input was valid? – Blackhole Aug 29 '15 at 11:20
  • +1 for research, and answering to the extent that you can try to justify the allowance of invalid dates, it replies to an extent.. though it'a hard to justify. The standard is clearly wrong at worst and poorly written at best. It looks like FF takes a sensible interpretation of a badly written ISO standard, and Chrome take a stupid interpretation of it. – barlop Aug 29 '15 at 11:38
3

The implementation differs between browsers. IE, Edge and Chrome will parse strings that doesn't represent actual dates, but Firefox will return NaN for those strings. The safe thing to do is to consider the result from Date.parse as undefined for date strings where the day falls outside the range of the month.

Browsers that allow parsing of non-existent dates will return a different date. Parsing "2015-04-31" will return the date 2015-05-01. This is the same behaviour as when using new Date(2015, 3, 31), where numbers out of range is allowed and will wrap around into a different month or year. That means that the result is still usable, if you don't mind that some invalid dates turn into other dates in some browsers.

The standard isn't very clear about what values are valid:

Illegal values (out-of-bounds as well as syntax errors) in a format string means that the format string is not a valid instance of this format.

The day component is defined as having a range from 1 to 31:

DD is the day of the month from 01 to 31.

However, the format is based on ISO 8601, and that is not a format for parsing strings into dates, that is a format for representing dates as string. Clearly you can't represent a date that doesn't even exist as a string.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • To nitpick on "you can't represent a date that doesn't even exist as a string": well, [technically](https://xkcd.com/1475/), that's the opposite; you can represent a date that doesn't exist as a string, but not as an object; there is a date string for `2015-04-31`, but not the corresponding object. – Blackhole Aug 29 '15 at 17:13
  • @Blackhole: Then it's not a date that is represented as a string, it's a string that looks similar to the representation of a date. – Guffa Aug 29 '15 at 19:30
0

Right, so how to check if a date string has a valid value?

with moment is very easy:

export function dateStringIsValid(aDateString){    
    return (moment(aDateString, "DD/MM/YYYY", true).isValid())   
}
Leo Bruno
  • 474
  • 3
  • 16