Date and Intl.DateTimeFormat
Creating and reading a Date correctly, a well-known month-indexing and time-zone-parsing pitfall, and formatting dates for a human reader.
new Date(year, month, day) / new Date(isoString) / new Intl.DateTimeFormat(locale, options).format(date)
Purpose
Date represents a single moment in time, internally as a timestamp — milliseconds since January
1, 1970 UTC. Intl.DateTimeFormat formats a Date for a human reader, locale-aware, the same way
Intl.NumberFormat handles numbers.
Syntax
const now = new Date();
const specific = new Date(2026, 8, 3); // September 3, 2026 — month is zero-indexed!
const fromISO = new Date('2026-09-03'); // parses an ISO date string
new Intl.DateTimeFormat('en-GB', { dateStyle: 'long' }).format(specific); // "3 September 2026"
Behavior notes
- The multi-argument constructor’s month is zero-indexed:
0is January,11is December.new Date(2026, 8, 3)is September 3rd, not August 3rd — a famous, easy-to-forget detail. - A date-only ISO string (
'2026-09-03', no time) parses as UTC midnight, not local midnight. Formatting it back with a local-time method can display the previous day depending on the reader’s time zone. A full ISO timestamp ('2026-09-03T00:00:00-04:00') avoids the ambiguity. - Subtracting two
Dateobjects (dateA - dateB) produces a numeric difference in milliseconds, usable for computing elapsed time or days between dates. date.getTime()(orNumber(date)) returns the millisecond timestamp directly.
Common mistakes
- Off-by-one-month bugs from forgetting the zero-indexed month.
- Off-by-one-day bugs from parsing a date-only string and displaying it in local time.
- Comparing two
Dateobjects with===— like any object, two differentDateinstances are never===even representing the same moment. Comparedate1.getTime() === date2.getTime()instead.
Runtime notes
Date is core ECMAScript; Intl.DateTimeFormat is part of the ECMAScript Internationalization API.
Both are supported identically across every current browser and Node version.