Date.prototype.getMonth()
Return the zero-based month index of a date according to local time.
getMonth()- Added in JavaScript ES1
Return value
numberAn integer between 0 and 11 representing the month of the given date according to local time, where 0 is January and 11 is December. Returns NaN if the date is invalid.
Errors
Throws a TypeError if called on a value that is not a Date object.
Returns the month as a zero-based index: January is 0, December is 11. The value is read in local time.
Why zero-based
The design assumes you will index an array of month names, which the indexing does cleanly. It matches the monthIndex argument of the Date constructor and of Date.UTC(), so a value taken from getMonth() can be fed straight back into either without adjustment.
What trips people up
Every off-by-one month bug in JavaScript starts here. Printing getMonth() for a display shows 7 for August; you need getMonth() + 1. Conversely, feeding a human month number back into the constructor without subtracting one produces a date a month late — and if that number is 12, the year rolls forward too.
The month is also the field most likely to change when you mutate a date. setMonth() keeps the day of the month, so moving 31 January forward by one month gives 2 March, because 31 February does not exist and normalizes into March. If you need month arithmetic that clamps, set the day to 1 first and then correct.
Note that getDate() is 1-based, so the two are not consistent with each other.
Example
When to use it
- Look up a month name from an array without an off-by-one adjustment
- Work out which calendar quarter a date falls into
- Group transactions by month for a summary table
- Rebuild a date with the same month but a different year
Frequently asked questions
Why does getMonth() return 7 for August?
The month is a zero-based index designed for array lookup, so January is 0 and August is 7. Add 1 when displaying it to a person.
How do I get the month name from a Date?
Index an array of names with getMonth(), or use new Intl.DateTimeFormat(locale, { month: "long" }).format(date) when the name must be localized.
Why did setMonth() land on the wrong month?
Because the current day of the month does not exist in the target month, so it normalized forward — 31 January plus one month becomes 2 or 3 March. Set the day to 1 before changing the month, then set the day you want.
More examples
Quarter and month padding
Dividing the zero-based index by 3 gives quarters with no adjustment. The formatter shows the +1 and the zero-padding that ISO-style month strings need.
function quarter(date) {
return Math.floor(date.getMonth() / 3) + 1;
}
function yyyymm(date) {
const m = String(date.getMonth() + 1).padStart(2, "0");
return `${date.getFullYear()}-${m}`;
}
console.log(quarter(new Date(2024, 0, 15)));
console.log(quarter(new Date(2024, 7, 15)));
console.log(yyyymm(new Date(2024, 8, 3)));
console.log(yyyymm(new Date(2024, 11, 31)));setMonth() overflow
31 February normalizes to 2 March, so getMonth() comes back as 2 even though 1 was set. Setting the day to 1 first keeps the result inside February.
const d = new Date(2024, 0, 31); // 31 January
d.setMonth(1); // ask for February
console.log(d.toDateString());
console.log(d.getMonth()); // 2, not 1
// Move the day first to keep the month you asked for
const safe = new Date(2024, 0, 31);
safe.setDate(1);
safe.setMonth(1);
console.log(safe.toDateString(), safe.getMonth());Grouping records by month
The index doubles as an array slot, so no conversion is needed. January totals 420, February is empty at 0, and March holds 75.
const sales = [
{ amount: 120, on: new Date(2024, 0, 5) },
{ amount: 300, on: new Date(2024, 0, 22) },
{ amount: 75, on: new Date(2024, 2, 11) },
];
const byMonth = new Array(12).fill(0);
for (const s of sales) byMonth[s.on.getMonth()] += s.amount;
console.log(byMonth);
console.log(byMonth[0], byMonth[1], byMonth[2]);
Discussion