ECMAScript Temporal API
Overview
Temporal is a global namespace (like Math) that provides a modern date/time API for ECMAScript, designed as a full replacement for the legacy Date object. It exposes over 200 utility methods across several classes, each handling a specific aspect of date and time management.
Temporal fixes the fundamental problems of Date:
- Separate types for date-only, time-only, zoned, and exact-time values — no ambiguous dual-role objects
- First-class timezone support with IANA identifiers, DST-safe arithmetic, and disambiguation controls
- Nanosecond precision via
epochNanoseconds(bigint) - Immutable instances — all operations return new objects, no mutating setters
- Multiple calendar systems beyond Gregorian (Hebrew, Chinese, Islamic, Japanese, etc.)
- Strict string parsing using RFC 9557 format based on ISO 8601 / RFC 3339
Temporal is not a constructor. All properties and methods are static. It is accessed as Temporal.Instant, Temporal.PlainDate, etc.
When to Use
- Replacing legacy
Datein new JavaScript/TypeScript projects - Performing date-time arithmetic that must be DST-safe
- Working with multiple time zones (conversions, offsets, transitions)
- Scheduling recurring events at specific wall-clock times
- Computing durations between dates/times with constrained units
- Working with non-Gregorian calendars
- Parsing or serializing date-time strings in RFC 9557 / ISO 8601 format
- Converting between legacy
Dateand modern Temporal types
Core Concepts
Class Hierarchy
Temporal classes fall into two categories: exact time (anchored to a real moment) and plain types (no timezone association).
| Category | Class | Represents |
|---|---|---|
| Exact time | Temporal.Instant |
A fixed point in time (nanoseconds since Unix epoch), no timezone or calendar |
| Exact time | Temporal.ZonedDateTime |
An instant + timezone + calendar — the broadest Temporal type |
| Plain | Temporal.PlainDateTime |
Date + time without timezone |
| Plain | Temporal.PlainDate |
Calendar date (year, month, day) without time or timezone |
| Plain | Temporal.PlainTime |
Wall-clock time (hour through nanosecond) without date or timezone |
| Plain | Temporal.PlainYearMonth |
Year + month without day (e.g., "October 2020 meeting") |
| Plain | Temporal.PlainMonthDay |
Month + day without year (e.g., "Bastille Day: July 14") |
| Duration | Temporal.Duration |
A length of time with signed units (years through nanoseconds) |
Utility namespace: Temporal.Now provides methods for getting the current system time in various formats.
Shared Interface
All Temporal classes share common method patterns:
- Construction:
new Type(...)orType.from(input)— parse from string, object, or existing instance - Immutability:
with(fields)— return a new instance with specified fields changed - Arithmetic:
add(duration),subtract(duration),since(other),until(other) - Comparison:
equals(other), staticType.compare(a, b) - Serialization:
toString(),toLocaleString(),toJSON()
Conversion Rules
Converting between exact and plain types requires explicit timezone choices:
Instant→ZonedDateTime: calltoZonedDateTimeISO(timeZone)ZonedDateTime→PlainDateTime: calltoPlainDateTime()(drops timezone)PlainDateTime→ZonedDateTime: calltoZonedDateTime(timeZone, { disambiguation })— must handle DST gaps/overlapsInstanthas no date/time component properties; a timezone is required to access year, month, day, hour, etc.
Representable Range
All date-bearing Temporal objects support approximately ±10⁸ days from the Unix epoch: -271821-04-20 to +275760-09-13. Objects refusing construction outside this range throw.
Quick Start
Getting current time
// Current exact instant
const now = Temporal.Now.instant();
now.epochMilliseconds; // number, like Date.now()
// Current date in system timezone
const today = Temporal.Now.plainDateISO();
today.toString(); // '2024-01-15'
// Current zoned date-time (instant + timezone + calendar)
const nowZoned = Temporal.Now.zonedDateTimeISO();
nowZoned.toString(); // '2024-01-15T10:30:00-05:00[America/New_York]'
Constructing objects
// From components
const date = new Temporal.PlainDate(2024, 6, 15);
const time = new Temporal.PlainTime(14, 30, 0);
// From strings (RFC 9557 format)
const instant = Temporal.Instant.from('2024-06-15T14:30:00Z');
const zoned = Temporal.ZonedDateTime.from('2024-06-15T14:30:00-04:00[America/New_York]');
// From object literals
const dt = Temporal.PlainDateTime.from({ year: 2024, month: 6, day: 15, hour: 14 });
Basic arithmetic
const date = Temporal.PlainDate.from('2024-06-15');
const later = date.add({ days: 7, months: 1 });
later.toString(); // '2024-07-22'
// Duration between two dates
const duration = date.until(later, { largestUnit: 'month' });
duration.months; // 1
duration.days; // 7
Immutability and updating
const date = Temporal.PlainDate.from('2024-06-15');
const modified = date.with({ day: 1 }); // original unchanged
modified.toString(); // '2024-06-01'
date.toString(); // '2024-06-15'
Converting from legacy Date
const legacy = new Date('2024-06-15T14:30:00Z');
const instant = legacy.toTemporalInstant();
const zoned = instant.toZonedDateTimeISO('America/New_York');
Advanced Topics
Temporal.Now and Instant: Getting current time, epoch nanoseconds, exact-time arithmetic → Temporal.Now and Instant
ZonedDateTime: Timezone-aware operations, DST handling, offset transitions, calendar properties → ZonedDateTime
Plain Types: PlainDate, PlainTime, PlainDateTime, PlainYearMonth, PlainMonthDay with shared patterns → Plain Types
Duration and Balancing: Duration construction, arithmetic, balancing modes, total(), rounding → Duration and Balancing
Time Zones and Calendars: IANA timezone identifiers, calendar systems, era/eraYear, monthCode, week properties → Time Zones and Calendars
String Formatting: RFC 9557 serialization, parsing patterns, toString/toLocaleString, format FAQ → String Formatting
Cookbook Patterns: Date interoperability, sorting, timezone conversion, business hours, recurring events, flight times → Cookbook Patterns