Date getters (getMonth, getDate, getDay…)

Nine methods that read the parts of a date. Two things to hold onto: months count from zero while days of the month count from one, and every one of these is local time.

Date methodsES1 (1997)Live demo
Common call
d.getMonth() + 1
Returns
a number, local to the runtime
Replaces
string slicing of a formatted date
Watch out
getMonth is 0–11; getDate is 1–31; getDay is the WEEKDAY
date.getFullYear(), date.getMonth(), date.getDate(), date.getDay()
→ number

Demo

Live evaluation
Try:
Inputs
isostringan ISO date, e.g. 2026-03-15T12:00:00Z
Output
(d => [d.getFullYear(), d.getMonth(), d.getDate(), d.getDay()])(new Date('2026-03-15T12:00:00Z'))
[2026, 2, 15, 0]

The four numbers are [year, month, date, day]. Look at the first case: a date in MARCH reports month 2, because getMonth counts from zero — while getDate reports 15, counting from one. Two adjacent methods on the same object with different bases, which is why so much date code is off by one month. The fourth number is getDay, the day of the WEEK (0 is Sunday), not the day of the month — another pair of confusingly similar names. An invalid date gives NaN from every getter rather than throwing.

Common patterns

Format a date manually
The +1 that every codebase contains.
const s = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
Name the weekday
getDay indexes an array of names.
const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
DAYS[d.getDay()];
Let Intl format it instead
No arithmetic, and locale-correct.
d.toLocaleDateString('en-GB', {month: 'long'});

Examples

1. March is 2
new Date('2026-03-15T12:00:00Z').getUTCMonth()
Returns
2
2. But the date is 15
new Date('2026-03-15T12:00:00Z').getUTCDate()
Returns
15
3. getDay is the weekday
new Date('2026-03-15T12:00:00Z').getUTCDay()
Returns
0 // Sunday
4. December is 11
new Date('2026-12-25T12:00:00Z').getUTCMonth()
Returns
11
5. Invalid gives NaN
new Date('nonsense').getMonth()
Returns
NaN
6. getYear is year − 1900
new Date('2026-03-15T12:00:00Z').getYear()
Returns
126

Pitfalls

1. getMonth is zero-based, getDate is not
The defining Date bug. Months run 0 to 11 and days of the month run 1 to 31, on the same object. Every manual format needs a +1 on the month and nothing on the date, and forgetting it produces a date one month early that still looks plausible.
A month early
`${d.getUTCMonth()}/${d.getUTCDate()}`
'2/15' for 15 March
Add one
`${d.getUTCMonth() + 1}/${d.getUTCDate()}`
'3/15'
2. getDay and getDate are different things
getDay is the day of the WEEK, 0 for Sunday. getDate is the day of the MONTH. The names are one character apart and both return a small number, so a mix-up type-checks, runs, and gives an answer that is wrong six days out of seven.
Weekday, not date
new Date('2026-03-15T12:00:00Z').getUTCDay()
0
Day of the month
new Date('2026-03-15T12:00:00Z').getUTCDate()
15
3. They are all local time
Every getter here reports the component as seen in the runtime timezone, so the same timestamp gives different numbers on a server in London and a laptop in Tokyo — and can differ by a whole DAY near midnight. Use the getUTC family when the answer must be stable.
Reader-dependent
new Date('2026-03-15T23:00:00Z').getDate()
15 or 16, depending on where
Stable
new Date('2026-03-15T23:00:00Z').getUTCDate()
15 everywhere
4. getYear is deprecated and returns year minus 1900
A survivor of the two-digit-year era. It returns 126 for 2026, which is neither the year nor a two-digit year. It exists only in Annex B — use getFullYear.
Not the year
new Date('2026-03-15T12:00:00Z').getYear()
126
getFullYear
new Date('2026-03-15T12:00:00Z').getFullYear()
2026

When to use

Use it
  • Reading a single component for arithmetic or comparison
  • Building a custom format where Intl options do not fit
  • Grouping records by local day, month or weekday
Reach for something else
  • Formatting for a reader → toLocaleDateString with Intl options
  • The answer must not depend on the runtime → the getUTC family
  • Serialising → toISOString
  • getYear, ever → getFullYear

Notes

Complexity
O(1) each, though local-time conversion consults timezone data
Return
A number, or NaN for an invalid Date
CPython impl
V8: Builtins-date getters
Memory
No allocation
Thread-safe
Single-threaded; the Date is only read

FAQ

Because it was designed to index an array of month names, in an era when that was how you formatted a date. getDate had no such use and stayed one-based. The inconsistency has been in the language since 1997 and cannot be changed.

const MONTHS = ['Jan', 'Feb', 'Mar'];
MONTHS[d.getMonth()];   // the original intent

History

ES1
The full getter family present from the first version, including the zero-based month and the deprecated getYear.
ES5
getYear and setYear formally relegated to Annex B.