0

I googled 'Javascript find number of days in month" and found this blog entry. I read it 5 times thinking "This won't work". But it does.

new Date(2022,8,0).getDate()

Can someone explain why/how this returns 31 instead of an error?

  • Because that's how JavaScript Date objects work. When you pass a value that is too large for the given unit, it rolls to the next higher unit. – Heretic Monkey Sep 03 '22 at 20:08
  • I *think* what you're saying is this: The date for `2022,8,14` is obviously 14, but the date for `2022,8,0` isn't valid, so it gives you the "previous" day in the month, which is kind of 31. –  Sep 03 '22 at 20:11
  • The relevant part of the spec is [MakeDay](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-makeday), an internal function implementations run which transforms the arguments. – Heretic Monkey Sep 03 '22 at 20:13
  • Can you explain like I'm an IT Director? :) –  Sep 03 '22 at 20:14
  • Will it surprise you that `new Date(2022,8,-1).getDate()` returns last day minus one (30) etc. ? – Konrad Sep 03 '22 at 20:16
  • Yes, it would... lol –  Sep 03 '22 at 20:20
  • 1
    [Specification is convoluted](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-makeday) but think of it as a modulo operation. So if a number is bigger than the maximum value it will be wrapped around. If it's negative it will be subtracted from the maximum value. It's usually how thing like that are handled in JS. – Konrad Sep 03 '22 at 20:25
  • 1
    "wrap" was the key word that made my brain understand. Thank you. –  Sep 03 '22 at 20:26
  • To drive it home to my stupid brain, I did `new Date(2022,8,35).getDate()` and of course, I got `5` since there were 30 days in August. –  Sep 03 '22 at 20:27
  • Wait... why wasn't it 4? There were 31 days in August. Why does `new Date(2022,8,31).getDate()` return `1` and not `31`? `2022,8,30` returns `30` as expected. –  Sep 03 '22 at 20:32
  • 2
    Related: https://stackoverflow.com/q/7556591/215552 – Heretic Monkey Sep 03 '22 at 20:34
  • 2
    Because 8 is September, not August (JavaScript months are 0-based). – Heretic Monkey Sep 03 '22 at 20:35
  • Jul and Aug both have 31, so I think it must be the timezone issue. Thanks –  Sep 03 '22 at 20:39

1 Answers1

1

Basically, the "why" is "the spec told us to". The ECMAScript specification says that the day portion of the values passed to the constructor should be made safe by taking the modulo of the value and 12. It is then passed through some other calculations such that values "wrap" to the preceding or succeeding month.

Passing string values drives these algorithms a little crazy, as answers to Is the Javascript date object always one day off? demonstrate.

In any case, taking care to validate arguments to the Date constructor beforehand before blindly taking what is returned is always a good idea.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • 1
    The real "why" is: because it was modeled after an outdated Java API, and the web took over 25 years to get an [update](https://tc39.es/proposal-temporal/docs/). – Bergi Sep 03 '22 at 22:49