It’s a little confusing, but according to documentation of Date
, the numerical value of the month is indexed to zero. That is, January is zero, February is 1, etc.
Therefore, new Date(1997, 1, 22)
creates a date for 22 de February de 1997. The method getMonth()
also uses this same rule, so in that case it will return 1
(corresponding to February).
But when the date is printed via console.log
, it is converted to some format (in this case, the format was "1997-02-22T03:00:00.000Z"), and then the month assumes the correct value (January is 1, February is 2, etc).
let d = new Date(1997, 1, 22);
console.log(d); // 1997-02-22T03:00:00.000Z
console.log(d.getMonth()); // 1
That is, depending on the situation, you have to try to use the values indexed in zero or 1.
In the builder of Date
(when it receives numeric values) and in the return of getMonth()
(and also in the past value for the method setMonth
), values are indexed to zero.
The methods that format the date use the correct value (indexed in 1):
let d = new Date(1997, 1, 22);
console.log(d.getMonth()); // 1
console.log(d.toISOString()); // 1997-02-22T03:00:00.000Z
console.log(d.toLocaleDateString('pt-BR')); // 22/02/1997
// mudando o mês para dezembro
d.setMonth(11);
console.log(d.toISOString()); // 1997-12-22T02:00:00.000Z
console.log(d.toLocaleDateString('pt-BR')); // 22/12/1997
Another point that might confuse you a little bit more is that when you pass a string in the ISO 8601 format for the manufacturer, then the months must have the correct values:
// passando uma string no formato ISO 8601, fevereiro deve ser mês 2
let d = new Date('1997-02-22');
console.log(d.getMonth()); // 1
console.log(d.toISOString()); // 1997-02-22T00:00:00.000Z
console.log(d.toLocaleDateString('pt-BR')); // 21/02/1997
But note that in that case there was a difference: the time is midnight in UTC (the "Z" at the end indicates that it is in UTC), and toLocaleDateString
returned day 21, because this method uses the browser Timezone (which in my case is in Brasilia Time), and as day 22 at midnight in UTC is equal to day 21 at 21h Brasilia Time, occurs this discrepancy.
When you use numeric values (new Date(1997, 1, 22)
), the Date
created corresponds to midnight in the browser Timezone (in this case, midnight in Brasilia time, which is equivalent to 3 am in UTC - so in the first case the time is printed as "03:00:00.000Z"). This behavior is explained in more detail here.
Just to make "even cooler" the builder of Date
does not complain if you spend a month greater than 11:
let d = new Date(1997, 12, 22);
console.log(d); // 1998-01-22T02:00:00.000Z
console.log(d.getMonth()); // 0
That is, if it passes the month 12, it creates a date referring to January of the following year.
My God, what madness hahaahah!! Very good your explanation! Thank you very much!! Now I understand this madness.. Javascript and its crazy points :S
– maiconfriedel
@Maikeaerosmith And note that dates aren’t even the craziest thing about Javascript, there are worse things: https://www.destroyallsoftware.com/talks/wat
– hkotsubo