Date.prototype.toISOString()
The one Date format with a single unambiguous meaning. It is also what toJSON returns, which is why a Date passed to JSON.stringify becomes an ISO string.
Demo
Every valid result has the same shape and ends in Z, which is what makes this format safe to store and compare as text. The second and third cases are the trap worth memorising: a DATE-ONLY string is parsed as UTC midnight, but a date-TIME string without a zone is parsed as LOCAL — so '2026-03-15' and '2026-03-15T00:00' are different instants, and the second one can land on the previous day once converted back to UTC. The last case is the other surprise: an invalid Date makes this method THROW, where toString would have returned 'Invalid Date'.
Common patterns
await save({createdAt: new Date().toISOString()});
JSON.stringify({at: new Date()});
const day = d.toISOString().slice(0, 10);
Examples
Pitfalls
new Date(userInput).toISOString()
const d = new Date(userInput); if (Number.isNaN(d.getTime())) reject(); d.toISOString();
new Date('2026-03-15T00:00').toISOString().slice(0, 10)
new Date('2026-03-15T00:00Z').toISOString().slice(0, 10)
new Date().toISOString().slice(0, 10)
new Date().toLocaleDateString('sv-SE')
new Date(Date.UTC(10000, 0, 1)).toISOString()
new Date(s).getUTCFullYear()
When to use
- Storing a date in a database or a file
- Sending a date over an API
- Logging, where a sortable unambiguous format matters
- Comparing dates as strings — ISO sorts correctly as text
- Showing a date to a person → toLocaleDateString
- The Date may be invalid → check getTime first, or it throws
- You need the local calendar day → a locale format, not a slice
- You need a zone-aware wall-clock time → store the zone separately
Notes
FAQ
Almost always because a date-time string without an offset was parsed as local time and then converted back to UTC. Append a Z if the input was meant to be UTC, or use a date-only string, which is parsed as UTC already.
new Date('2026-03-15T00:00'); // local new Date('2026-03-15T00:00Z'); // UTC new Date('2026-03-15'); // UTC