Cheatsheet

JavaScript Date Cheatsheet

The JavaScript Date object stores one number, the milliseconds since the Unix epoch (1970-01-01T00:00:00Z), and every getter and formatter is a view of that number in a time zone. This sheet is for developers who parse date strings, do date math or format dates for display. The confusion it clears up: the same string can parse to different instants depending on whether it has a time part, and months count from 0.

Quick reference

Create a Date

Expression Result
`new Date()` Now
`Date.now()` Now as a number of milliseconds, no object
`new Date(ms)` From a timestamp in milliseconds
`new Date('2026-10-05T09:30:00+02:00')` From an ISO string, `2026-10-05T07:30:00.000Z`
`new Date(2026, 9, 5)` Local midnight, month 9 is October
`new Date(Date.UTC(2026, 9, 5, 12))` UTC components, `1791201600000`
`new Date(otherDate)` Copy
`Date()` without `new` A string, not an object

Getters

Local UTC Range
`getFullYear()` `getUTCFullYear()` Four-digit year
`getMonth()` `getUTCMonth()` 0 to 11
`getDate()` `getUTCDate()` 1 to 31
`getDay()` `getUTCDay()` 0 (Sunday) to 6
`getHours()` `getUTCHours()` 0 to 23
`getMinutes()` `getUTCMinutes()` 0 to 59
`getSeconds()` `getUTCSeconds()` 0 to 59
`getMilliseconds()` `getUTCMilliseconds()` 0 to 999
`getTime()` or `valueOf()` same Milliseconds since the epoch
`getTimezoneOffset()` none Minutes, UTC minus local, so New York in summer is `240`

Each getter has a set twin, such as setDate(n), setMonth(m, d) and setUTCHours(h). Setters mutate the object and return the new timestamp.

Output methods

Values below are for Date.UTC(2026, 9, 5, 12) with the process time zone set to America/New_York.

Method Output
`toISOString()` `2026-10-05T12:00:00.000Z`
`toJSON()` `2026-10-05T12:00:00.000Z`
`toUTCString()` `Mon, 05 Oct 2026 12:00:00 GMT`
`toString()` `Mon Oct 05 2026 08:00:00 GMT-0400 (Eastern Daylight Time)`
`toDateString()` `Mon Oct 05 2026`
`toLocaleDateString('en-US')` `10/5/2026`
`toLocaleDateString('en-GB')` `05/10/2026`
`toLocaleDateString('de-DE')` `5.10.2026`
`toLocaleTimeString('en-US')` `8:00:00 AM`

Limits and special values

Fact Value
Latest representable time `8.64e15` ms, `+275760-09-13T00:00:00.000Z`
Earliest representable time `-8.64e15` ms, `-271821-04-20T00:00:00.000Z`
Beyond the range `NaN`, shown as `Invalid Date`
Invalid check `isNaN(date)` or `Number.isNaN(date.getTime())`
Two-digit year in the constructor `new Date(99, 0, 1)` is 1999
Year 100 and up Taken literally, `new Date(100, 0, 1)` is year 100

Common patterns

Parse an ISO string and see where it lands

console.log(new Date('2026-10-05').toISOString());
console.log(new Date('2026-10-05T00:00:00').toISOString());
console.log(new Date('2026-10-05T00:00:00Z').toISOString());
2026-10-05T00:00:00.000Z
2026-10-05T04:00:00.000Z
2026-10-05T00:00:00.000Z

Run with TZ=America/New_York. A date-only string is read as UTC, a date-time without an offset is read as local time, and a trailing Z or offset is exact. Add an offset or Z whenever the time zone matters.

Format a date for people

const d = new Date(Date.UTC(2026, 9, 5, 12));
console.log(d.toLocaleDateString('en-US', {weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC'}));
console.log(d.toLocaleString('en-US', {dateStyle: 'medium', timeStyle: 'short', timeZone: 'UTC'}));
console.log(d.toLocaleString('en-US', {timeZone: 'Asia/Tokyo', hour12: false}));
Monday, October 5, 2026
Oct 5, 2026, 12:00 PM
10/5/2026, 21:00:00

Pass timeZone to format in any IANA zone without changing the Date. The JS Intl.DateTimeFormat Playground lets you try the options interactively.

Add days without breaking on daylight saving

const day = new Date(2026, 9, 31, 12);
console.log(new Date(day.getTime() + 24 * 3600e3).toString());
const dd = new Date(day);
dd.setDate(dd.getDate() + 1);
console.log(dd.toString());
Sun Nov 01 2026 11:00:00 GMT-0500 (Eastern Standard Time)
Sun Nov 01 2026 12:00:00 GMT-0500 (Eastern Standard Time)

Adding 24 hours of milliseconds crossed the November 1 clock change and landed at 11:00. setDate keeps the wall-clock time. Use milliseconds only for durations, and setDate or setMonth for calendar steps.

Get the days in a month and the days between dates

console.log(new Date(2026, 2, 0).getDate(), new Date(2026, 1, 0).getDate(), new Date(2024, 2, 0).getDate());
console.log(Math.round((new Date('2026-12-25') - new Date('2026-10-05')) / 864e5));
28 31 29
81

Day 0 of a month is the last day of the previous month, so new Date(2026, 2, 0) gives 28 for February 2026. Both strings above are date-only, so both are UTC and the difference is a clean multiple of 86,400,000.

Convert to and from Unix time

const d = new Date(Date.UTC(2026, 9, 5, 12));
console.log(d.getTime(), Math.floor(d / 1000), +d);
console.log(JSON.stringify({d}));
1791201600000 1791201600 1791201600000
{"d":"2026-10-05T12:00:00.000Z"}

getTime() is milliseconds. Divide by 1000 and floor it for the seconds that most APIs use. Unix Timestamp Converter handles both units.

Compare two dates

console.log(new Date('2026-10-05') < new Date('2026-10-06'));
console.log(new Date(0) == new Date(0), new Date(0).getTime() === new Date(0).getTime());
true
false true

Relational operators coerce to numbers, but and = compare object identity. Compare getTime() values for equality.

Validate a calendar date from parts

const ok = (y, m, d) => {
  const x = new Date(y, m - 1, d);
  return x.getFullYear() === y && x.getMonth() === m - 1 && x.getDate() === d;
};
console.log(ok(2026, 2, 28), ok(2026, 2, 30), ok(2024, 2, 29));
true false true

The constructor rolls impossible dates forward instead of failing, so build the date and read the parts back. If any part differs, the input was not a real date. This also handles leap years.

Print a date as YYYY-MM-DD

const s = new Date('2026-10-05T12:00:00Z');
console.log(s.toISOString().slice(0, 10));
2026-10-05

The first ten characters of toISOString() are the UTC calendar date. For the local calendar date, assemble it from getFullYear(), getMonth() + 1 and getDate() with padStart(2, '0').

Pitfalls

  • Months start at 0: new Date(2026, 10, 1) is November 1, not October 1. Days start at 1, and getDay() returns the weekday 0 to 6, not the day of the month.
  • Date-only strings parse as UTC: in New York, new Date('2026-10-05').getDate() returned 4, and toLocaleDateString('en-US') printed 10/4/2026. Format with timeZone: 'UTC' or build the date from parts.
  • Date-time strings without an offset parse as local: '2026-10-05T00:00:00' is a different instant on every machine. Server and browser then disagree. Send Z or an offset.
  • Non-ISO strings: new Date('05/10/2026') was read as May 10 in Node 22, not October 5. Formats outside the ISO profile are implementation-defined, so parse them yourself.
  • Out-of-range ISO values in V8: Node 22 turned '2026-02-30' into 2026-03-02T00:00:00.000Z instead of an invalid date. Do not rely on rollover from strings, and validate the parts first.
  • Setter rollover: setMonth(1) on January 31 gave Tue Mar 03 2026, because February has no 31st. Set the day to 1 first, or clamp it.
  • Invalid Date does not throw: new Date('nope') prints Invalid Date and getTime() is NaN. Only toISOString() throws, with RangeError: Invalid time value. Check with isNaN(date).
  • Nonexistent local times: new Date(2026, 2, 8, 2, 30) in New York, a skipped hour, came back as 03:30:00 GMT-0400. Use UTC for scheduling.
  • JSON.stringify loses the type: a Date becomes an ISO string, and JSON.parse returns a string, not a Date. Convert back with new Date(value).

Related ZipKit tools

  • Unix Timestamp Converter — convert timestamps in seconds or milliseconds to dates and back
  • JS Intl.DateTimeFormat Playground — try dateStyle, timeStyle and timeZone options and see the output

Related cheatsheets