What is the Temporal API?
The Temporal API is a new built-in API for working with dates and time in JavaScript (officially at the final-standard stage as of ES2024).
Its goal is to replace the "broken" Date and provide precise, safe, convenient tools for all time-related operations.
Why Temporal was created at all
Date is one of the oldest and most problematic parts of JS (dating back to 1995):
| Problem | Example |
|---|---|
| Implicit time zones | new Date('2024-01-01') -> the result depends on your region |
| Unpredictable calculations | new Date(2024, 1, 30) -> March 1 |
| Mutating methods | setMonth(), setHours() mutate the original object |
| Poor UTC handling | You often need to convert manually via toISOString(), getUTC*() |
| No proper API for calendars, durations, and time zones |
Temporal solves all of these problems by introducing a clear model of time and immutable objects.
The main idea behind the Temporal API
Temporal provides new classes that work with different aspects of time:
| Class | What it represents | Example |
|---|---|---|
Temporal.Instant | A moment in time (a point in UTC) | "2025-10-16T21:00:00Z" |
Temporal.PlainDate | A date without a time | "2025-10-16" |
Temporal.PlainTime | A time without a date | "21:00:00" |
Temporal.PlainDateTime | A date and time without a time zone | "2025-10-16T21:00:00" |
Temporal.ZonedDateTime | Date + time + time zone | "2025-10-16T21:00:00+02:00[Europe/Warsaw]" |
Temporal.Duration | The difference between two moments (a duration) | "P3DT5H" (3 days 5 hours) |
Temporal.Now | A utility for getting the current time | - |
Example: creating a date and time
// A plain date
const date = Temporal.PlainDate.from('2025-10-16');
console.log(date.year, date.month, date.day); // 2025 10 16
// A time
const time = Temporal.PlainTime.from('13:45:30');
console.log(time.hour); // 13
// A date and time
const dt = Temporal.PlainDateTime.from('2025-10-16T13:45:30');
console.log(dt.toString()); // 2025-10-16T13:45:30Example: working with time zones
const zdt = Temporal.ZonedDateTime.from({
timeZone: 'Europe/Warsaw',
year: 2025,
month: 10,
day: 16,
hour: 21,
});
console.log(zdt.toString());
// 2025-10-16T21:00:00+02:00[Europe/Warsaw]
console.log(zdt.toInstant().toString());
// 2025-10-16T19:00:00Z (in UTC)Temporal stores the time zone as part of the data ([Europe/Warsaw]),
not just an offset like +02:00.
Example: calculations with dates and time
const today = Temporal.PlainDate.from('2025-10-16');
const tomorrow = today.add({ days: 1 });
const lastWeek = today.subtract({ weeks: 1 });
console.log(tomorrow.toString()); // 2025-10-17
console.log(lastWeek.toString()); // 2025-10-09All objects are immutable; operations return new values instead of changing the original object.
Example: calculating a duration
const start = Temporal.PlainDateTime.from('2025-10-16T10:00');
const end = Temporal.PlainDateTime.from('2025-10-18T15:30');
const duration = end.since(start);
console.log(duration.toString()); // P2DT5H30M (2 days 5 hours 30 minutes)Example: the current time and the time in a zone
const now = Temporal.Now.instant();
console.log(now.toString()); // The current UTC time
const warsaw = Temporal.Now.zonedDateTimeISO('Europe/Warsaw');
console.log(warsaw.toString());
// For example: 2025-10-16T23:50:00+02:00[Europe/Warsaw]Example: the difference from Date
// Date
new Date(2025, 1, 30) // 2025-03-02 (!) -> an automatic "rollover"
// Temporal
Temporal.PlainDate.from({ year: 2025, month: 1, day: 30 });
// RangeError: Invalid PlainDateTemporal strictly validates dates; there are no "automatic corrections".
Example: formatting and parsing ISO strings
const zdt = Temporal.ZonedDateTime.from('2025-10-16T21:00+02:00[Europe/Warsaw]');
console.log(zdt.toString()); // 2025-10-16T21:00:00+02:00[Europe/Warsaw]It supports the full ISO 8601 format and works with time zones through the IANA database (the same one used by Intl.DateTimeFormat).
Example: using it with Intl
You can conveniently format dates and times for the user:
const zdt = Temporal.ZonedDateTime.from('2025-10-16T21:00:00+02:00[Europe/Warsaw]');
const fmt = new Intl.DateTimeFormat('en-US', { dateStyle: 'full', timeStyle: 'long' });
console.log(fmt.format(zdt));
// Thursday, October 16, 2025 at 9:00:00 PM GMT+2Example: safely handling time zones
const beforeDST = Temporal.ZonedDateTime.from('2025-03-30T01:30:00+01:00[Europe/Berlin]');
const afterDST = beforeDST.add({ hours: 1 });
console.log(afterDST.toString());
// 2025-03-30T03:30:00+02:00[Europe/Berlin]Temporal understands daylight saving transitions and shifts the hours correctly.
Benefits of the Temporal API
| Benefit | What it gives |
|---|---|
| Immutability | Safe operations without mutations |
| A clear model | Separation of the concepts "date", "time", "zone" |
| Accurate time zone handling | Uses the IANA database |
No Date "magic" | Errors instead of silent corrections |
Compatible with Intl | Clean formatting |
| ISO and Duration support | Simple handling of differences and intervals |
Where it can already be used
- Node.js 20+ - built in natively
- Modern browsers (Chrome 115+, Firefox 122+, Edge 115+)
- Older environments - via a polyfill
@js-temporal/polyfill
npm i @js-temporal/polyfillimport { Temporal } from '@js-temporal/polyfill';Summary
| Object | Description |
|---|---|
Temporal.Instant | an absolute point in time (UTC) |
Temporal.PlainDate, PlainTime, PlainDateTime | local values without a zone |
Temporal.ZonedDateTime | date + time + time zone |
Temporal.Duration | a duration (a time difference) |
Temporal.Now | access to the current time |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.