Date has been a source of bugs for decades: it is mutable, months are zero-based, parsing is inconsistent, and time zones are implicit. Temporal replaces it with a set of explicit, immutable types.
Support today
Chrome and Edge 144 (January 2026) and Firefox 139 support Temporal, and recent Node.js versions enable it too. Safari has not shipped it, which also affects every browser on iOS. If you need Safari, use the official polyfill and budget for its bundle size. Check current support before relying on it.
Pick the right type
Temporal.Instant: an exact point in time (like a UTC timestamp).Temporal.PlainDate: a calendar date with no time or zone (a birthday).Temporal.PlainDateTime: date and time with no zone.Temporal.ZonedDateTime: a moment in a specific time zone, with DST handled correctly.Temporal.Duration: an amount of time.
const meeting = Temporal.ZonedDateTime.from(
'2026-10-25T09:00[Europe/Kyiv]',
);
// Same instant, shown in another zone
const inNewYork = meeting.withTimeZone('America/New_York');
console.log(inNewYork.toString());
Arithmetic without surprises
Every operation returns a new object, so shared values are never mutated by accident.
const start = Temporal.PlainDate.from('2026-01-31');
const next = start.add({ months: 1 });
console.log(next.toString()); // 2026-02-28 (clamped, no overflow into March)
const until = Temporal.PlainDate.from('2026-12-31').since(start, {
largestUnit: 'months',
});
console.log(until.months, until.days);
With Date, new Date(2026, 0, 31) plus one month silently becomes March 3. Temporal clamps to the last valid day by default.
Comparing and sorting
const dates = [
Temporal.PlainDate.from('2026-05-01'),
Temporal.PlainDate.from('2026-03-15'),
];
dates.sort(Temporal.PlainDate.compare);
Using it in TypeScript
TypeScript 6.0 includes Temporal types through esnext or the more specific esnext.temporal library. Add "esnext.temporal" to your lib setting alongside the libraries your project already uses. Types do not add runtime support; browsers without Temporal still need a polyfill.
// Include "esnext.temporal" in compilerOptions.lib
export function daysUntil(deadline: Temporal.PlainDate): number {
const today = Temporal.Now.plainDateISO();
return today.until(deadline, { largestUnit: 'days' }).days;
}
When to migrate
Use Temporal for new code where you control the browsers or can ship the polyfill. Keep Date at API boundaries until your support matrix allows more. Convert at the edge with Temporal.Instant.fromEpochMilliseconds(date.getTime()).