Date.prototype.getTime()
A Date contains nothing but this number. Everything else — components, formatting, timezones — is computed from it on demand, which explains most of the API surprises.
Demo
One number, counting milliseconds from midnight UTC on 1 January 1970 — so the epoch itself is 0 and anything earlier is negative. That single number IS the Date; there is no timezone stored anywhere in it. The invalid case gives NaN, and because NaN is never equal to itself, the idiomatic validity check is Number.isNaN(d.getTime()) rather than a comparison.
Common patterns
if (a.getTime() === b.getTime()) { }
const valid = !Number.isNaN(d.getTime());
const days = (b - a) / 86400000;
Examples
Pitfalls
new Date(0) === new Date(0)
new Date(0).getTime() === new Date(0).getTime()
new Date(0) == new Date(0)
new Date(0) <= new Date(0)
new Date('nonsense').getTime() + 1000
const t = new Date(s).getTime(); if (Number.isNaN(t)) reject();
(b - a) / 86400000
Math.round((Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()) - Date.UTC(a.getFullYear(), a.getMonth(), a.getDate())) / 86400000)
When to use
- Comparing two Dates for equality or ordering
- Checking whether a parsed Date is valid
- Storing or transmitting a date as a number
- Measuring a difference between two instants
- Comparing Dates with === → it compares references
- Counting calendar days across DST → compare UTC date parts
- Measuring elapsed code time → performance.now()
- Human-readable output → toISOString or a locale format
Notes
FAQ
Because arithmetic and relational operators coerce objects to primitives via valueOf, which returns the timestamp. Strict equality does no coercion at all — it compares object identity. So a - b works, a < b works, and a === b is always false for distinct objects.
b - a; // milliseconds a < b; // correct a === b; // false, always a.getTime() === b.getTime(); // correct