This has been asked (badly) before - I don't think the answer in that post really addressed the issue, and then it went stale. I'm going to attempt to ask it again with a clearer demonstration of the issue.
The implementation of Javascript Date.setMonth()
appears not to follow the principle of least surprise. Try this in a browser console:
d = new Date('2017-08-31') // Set to last day of August
d.getMonth() // 7 - months are zero-based
d.setMonth(8) // Try to set the month to 8 (September)
d.getMonth() // 9 - October. WTF Javascript?
Similarly:
d = new Date('2017-10-31')
d.getMonth() // 9
d.setMonth(8)
d.getMonth() // 9 (still?)
Firefox on Linux appears even worse - sometimes returning a date in October, and a result from getMonth()
which doesn't match that month!
My question (and I think that of the OP from that linked question) is how to consistently implement a 'next' / 'prev' month function in, e.g. a datepicker? Is there a well known way of doing this which doesn't surprise the user by, for example, skipping September when they start on August 31st and click 'next'? Going from January 31st is even more unpredictable currently - you will end up on either March 2nd or March 3rd, depending on whether it's a leap year or not!
My personal view is that the least surprise would be to move to the last day of the next / previous month. But that requires the setMonth()
implementation to care about the number of days in the months in question, not just add / subtract a fixed duration. According to this thread, the moment.js
approach is to add / subtract the number of milliseconds in 30 days, which suggests that library would be prone to the same inconsistencies.