Date objects in JavaScript — the tricky parts

Let's assume it's 30 September 2020. It may seem counter-intuitive, but the current date plays a big role when creating Date objects in JavaScript.

Here's the first part of the problem.

let date = new Date();

date.setYear(2020); // 2020
date.setDate(31); // 31
date.setMonth(7); // August

// Result: Sat Aug 01 2020 14:26:55 GMT+0200

Side note: When using the setMonth method it's important to remember months are indexed starting from 0. January is at position 0, December is at position 11. In the example above I'm using 7 as an index of August.

Now that's a very strange result.

The resulting Date object's day of the month is 01.

Before we start pulling the hair out let's break it down and consider what's going on here. We're creating a Date object first, then setting the year, then the month and finally the day of the month. At the time we're setting the date to 31 it's assumed the month is September (based on the current date). Since September 2020 has only 30 days, the day of the month gets "autocorrected" to 01.

This "autocorrecting" feature seems like a good idea, but in the end causes more problems than it solves. At the end of the day we have to be aware of the way things work in JavaScript land.

You might be tempted to switch the order of the calls and call setMonth first, followed by setDate. This partly solves the issue, at least when we consider the example above.

Being smarter now let's try to create a different Date object and set the date to 15 February 2020.

let date = new Date();

date.setYear(2020); // 2020
date.setMonth(1); // February
date.setDate(15); // 15

// Result: Sun Mar 15 2020 14:13:14 GMT+0100

Why is it a date in March all of a sudden if we switched the order of the calls and are calling setMonth first? It's a similar problem at play...

At the time of calling setMonth it's assumed the day of the month is 30 (based on the current date again). Since February 2020 has only 29 days the month gets "autocorrected" to March.

I think this proves switching the order of the calls didn't really solve the problem.

What's the solution?

let date = new Date(2020, 7, 31);
// Result: Mon Aug 31 2020 00:00:00 GMT+0200

date = new Date(2020, 1, 15);
// Result: Sat Feb 15 2020 00:00:00 GMT+0100

Always pass the year/month/day of the month to the Date constructor.