Table of Contents

JavaScript’s Temporal API officially reached TC39 Stage 4 on March 11, 2026, making it part of the ES2026 specification. Chrome 144 and Firefox 139 already ship it natively. After nine years of standardization work and three decades of new Date() bugs, JavaScript now has a proper date-and-time primitive—immutable, timezone-aware, and nanosecond-precise.


What Is the Temporal API?

Temporal is a new set of built-in JavaScript objects for representing and manipulating dates, times, and durations. It does not patch the existing Date object—it replaces it with a purpose-built family of types that address every major failure mode of Date at the language level.1

Where Date is a single mutable object that conflates calendar dates, wall-clock times, UTC instants, and timezone offsets into one confused blob, Temporal offers distinct types for each semantic concept. You reach for the right type and the API prevents the class of bugs that follow from picking the wrong one.

The core types are:

TypeWhat It RepresentsTypical Use Case
Temporal.PlainDateCalendar date (no time, no zone)Birthdays, deadlines, holidays
Temporal.PlainTimeWall-clock time (no date, no zone)Business hours, alarm times
Temporal.PlainDateTimeDate + time, no timezoneLog entries, local schedules
Temporal.ZonedDateTimeDate + time + IANA timezoneCalendar events, user-facing timestamps
Temporal.InstantExact moment (nanoseconds since epoch)Metrics, event ordering, serialization
Temporal.DurationSpan of timeCountdowns, elapsed time
Temporal.NowUtilities for current timeReplacements for Date.now()

Why Did JavaScript’s Date Object Need Replacing?

The Date object was written by Brendan Eich in 1995 in approximately 10 days, copied almost directly from Java’s java.util.Date class. Java itself had copied the design from C, which traces the zero-indexed month convention back to Research Unix V4 in 1973.2

That lineage explains every maddening quirk of Date:

Zero-indexed months. January is 0, December is 11. Days of the month are one-indexed. Years are normal. The inconsistency has no rational justification and has burned developers for 30 years.

// Date: January is 0
const date = new Date(2026, 0, 15); // January 15th
date.getMonth(); // → 0
// Temporal: January is 1
const tDate = Temporal.PlainDate.from({ year: 2026, month: 1, day: 15 });
tDate.month; // → 1

Mutability. Date methods like setDate(), setMonth(), and setFullYear() modify the object in place, making functions that accept dates unpredictable. Pass a Date into a function; that function can silently alter it.

// Date: mutable, side-effect prone
const deadline = new Date(2026, 2, 31);
deadline.setDate(deadline.getDate() + 7); // mutates deadline
console.log(deadline); // April 7 — the original date is gone
// Temporal: immutable, returns a new object
const tDeadline = Temporal.PlainDate.from('2026-03-31');
const extended = tDeadline.add({ days: 7 });
console.log(tDeadline.toString()); // '2026-03-31' — unchanged
console.log(extended.toString()); // '2026-04-07'

No real timezone support. Date stores a UTC millisecond timestamp and renders it in the host machine’s local timezone. It does not understand IANA timezone names like America/New_York. It tracks offsets—integers like -05:00—not the rules that govern them. When DST transitions occur, Date arithmetic can produce results that are off by an hour, and the behavior has differed across browsers.3

Browser inconsistencies. Feeding new Date('2026-01-15') a date-only string returns midnight UTC in most browsers but midnight local time in others. The spec was underspecified for parsing, and implementations diverged accordingly.

Millisecond ceiling. Date.now() maxes out at millisecond precision. Temporal.Instant stores nanoseconds since the Unix epoch—6 orders of magnitude more granular—without requiring performance.now() gymnastics.4


How the Temporal API Solves These Problems

Type Safety Through Separation

The explicit separation between PlainDate, PlainDateTime, and ZonedDateTime forces developers to declare whether timezone matters—at the type level, not as documentation or convention.

// A date-only value: no accidental timezone arithmetic
const birthday = Temporal.PlainDate.from('1991-06-15');
// A precise, timezone-aware event
const meeting = Temporal.ZonedDateTime.from(
'2026-03-20T14:00:00[America/New_York]'
);
// Current moment with full nanosecond precision
const now = Temporal.Now.instant();
console.log(now.epochNanoseconds); // e.g., 1742000000000000000n

Arithmetic That Respects Reality

Duration-based arithmetic in Temporal understands DST. Adding one day to a ZonedDateTime gives you the next calendar day at the same wall-clock time—not 24 hours later, which might land in the wrong hour after a DST transition.

const beforeDST = Temporal.ZonedDateTime.from(
'2026-03-07T10:00:00[America/New_York]'
); // Day before spring forward
// Add 1 day: lands at 10:00 AM even though 25 hours pass in UTC
const afterDST = beforeDST.add({ days: 1 });
console.log(afterDST.toString());
// 2026-03-08T10:00:00-04:00[America/New_York]

Deterministic Parsing

Temporal.PlainDate.from() throws a RangeError on invalid input rather than silently returning Invalid Date or guessing. There is no ambiguity: the string format is ISO 8601, strictly enforced.

// Date: silent failure
new Date('not-a-date'); // Invalid Date — no error thrown
// Temporal: strict validation
Temporal.PlainDate.from('not-a-date'); // throws RangeError

Calendar System Support

Temporal ships with support for non-Gregorian calendar systems as a first-class concern—Islamic, Hebrew, Japanese, Chinese calendars among them. Internationalization no longer requires external libraries for calendar-aware date arithmetic.5


Nine Years: How Web Standards Actually Get Made

The Temporal proposal entered TC39 at Stage 1 in 2017, championed by Maggie Johnson-Pint, who had spent years maintaining Moment.js and knew the ecosystem’s pain intimately.6 The problem was not controversial—the committee recognized Date was broken immediately. The difficulty was design.

Date-and-time is one of the most semantically complex domains in computing. Timezones change. Calendars differ across cultures. DST rules are revised by governments with little notice. A design adequate for 2017 web apps needed to remain coherent for the next 20 years of JavaScript.

Bloomberg became a significant force in moving the proposal forward. Bloomberg engineers already worked with value-semantic datetime types internally. When Bloomberg’s Andrew Paprocki connected with Igalia and Daniel Ehrenberg at TC39, it created a bridge between production engineering needs and standards infrastructure.7 Bloomberg and Igalia funded sustained implementation work in browser engines—the unglamorous work of turning a spec into shipping code across V8, SpiderMonkey, and JavaScriptCore.

Progress stalled repeatedly. Stage 3 was reached in 2021 but the proposal sat there for four years while implementations were written, edge cases identified, and spec text refined. Firefox 139 was the first browser to ship Temporal by default, in May 2025. Chrome 144 followed in January 2026.8

On March 11, 2026, at TC39’s 113th plenary meeting in New York, Temporal advanced to Stage 4—the final stage, meaning ratification into ES2026.9


What This Means for the Ecosystem

The Date Library Era Is Ending

Moment.js declared itself in maintenance mode years ago, explicitly citing Temporal as the long-term successor.10 Luxon, date-fns, and Day.js remain relevant for applications supporting browsers without native Temporal—primarily Safari, which has not yet shipped a stable release (as of March 2026, Safari supports Temporal only in Technology Preview).

For new projects targeting Chrome and Firefox, Temporal covers what these libraries provided without the bundle weight. Moment.js adds 67KB minified to a bundle; Temporal costs nothing.

Polyfill for the Transition Period

The @js-temporal/polyfill npm package provides compatibility for environments without native support. It adds meaningfully less bundle size than Moment or moment-timezone, though the polyfill team notes it should be treated as beta-quality for production use.11

Terminal window
npm install @js-temporal/polyfill
import { Temporal } from '@js-temporal/polyfill';
const today = Temporal.Now.plainDateISO();
console.log(today.toString()); // '2026-03-15'

TypeScript 6.0 Ships Native Types

TypeScript 6.0 RC, released March 6, 2026, includes built-in type definitions for the entire Temporal API. Enable them with "lib": ["esnext"] or the granular "temporal.esnext" lib entry—no @types/ package required.12

Node.js and Deno

Node.js 22+ exposes Temporal via V8 once the flag is enabled; Node 23 is expected to ship it unflagged. Deno already includes full Temporal support through its web-standard-first approach.


The Comparison: Old Patterns vs. New

ConcernLegacy DateTemporal
Month indexing0–11 (January = 0)1–12 (January = 1)
MutabilityMutable in placeImmutable, returns new objects
Timezone supportOffset only (-05:00)Full IANA names (America/New_York)
PrecisionMillisecondsNanoseconds
ParsingAmbiguous, browser-dependentStrict ISO 8601, throws on error
Calendar systemsGregorian only12+ calendars including Hebrew, Islamic, Japanese
Duration arithmeticManual millisecond mathadd({ months: 1 }), DST-aware
Comparisondate1 - date2 (numeric coercion)Temporal.PlainDate.compare(a, b)
Type separationOne object for everythingDistinct types per semantic concept


Frequently Asked Questions

Q: Is Date being removed from JavaScript? A: No. Date remains in the language permanently for backward compatibility. Temporal is an addition, not a replacement at the removal level—but it is the API you should use going forward.

Q: Can I use Temporal in production today? A: In Chrome 144+ and Firefox 139+, yes—it ships natively. For Safari support you need the @js-temporal/polyfill, which the team considers beta-quality. If your user base is primarily Chrome/Firefox, native Temporal is production-ready as of March 2026.

Q: Does Temporal replace performance.now() for timing? A: Not exactly. Temporal.Now.instant() provides nanosecond precision for timestamps, but performance.now() remains the standard for high-resolution relative timing within a session. They serve different purposes: Temporal for absolute time points and durations; performance.now() for benchmarking and animation frames.

Q: How do I migrate existing code that uses Moment.js? A: Smashing Magazine published a migration guide in March 2026 covering the Moment-to-Temporal path. The key shift is conceptual: stop thinking in mutable Date wrappers and start thinking in typed, immutable value objects. Most moment(date).add(7, 'days') calls map directly to temporalDate.add({ days: 7 }).

Q: What happens to TypeScript users before TypeScript 6.0? A: Install @js-temporal/polyfill, which ships its own TypeScript definitions. Alternatively, the @types/temporal-polyfill community package provides type coverage. TypeScript 6.0 stable (expected March 2026) resolves the question for everyone on the current toolchain.


Sources:

Footnotes

  1. MDN Web Docs. “Temporal - JavaScript.” Mozilla, March 2026. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal

  2. Jeff Kaufman. “History of Zero-based Months?” jefftk.com. https://www.jefftk.com/p/history-of-zero-based-months

  3. Matt Johnson-Pint. “JavaScript Date type is horribly broken.” codeofmatt.com. https://codeofmatt.com/javascript-date-type-is-horribly-broken/

  4. MDN Web Docs. “Temporal.Instant.” Mozilla, 2026. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant

  5. TC39 Proposal. “Temporal Documentation.” tc39.es. https://tc39.es/proposal-temporal/docs/

  6. Bloomberg Engineering. “Temporal: The 9-Year Journey to Fix Time in JavaScript.” Bloomberg JS Blog. https://bloomberg.github.io/js-blog/post/temporal/

  7. Igalia. “Temporal Reaches Stage 4.” March 13, 2026. https://www.igalia.com/2026/03/13/Temporal-Reaches-Stage-4.html

  8. InfoQ. “Chrome 144 Ships Temporal API: Advancing JavaScript Date/Time Standardisation.” February 2026. https://www.infoq.com/news/2026/02/chrome-temporal-date-api/

  9. The New Stack. “ES2026 Solves JavaScript Headaches With Dates, Math and Modules.” March 2026. https://thenewstack.io/es2026-solves-javascript-headaches-with-dates-math-and-modules/

  10. Moment.js. “Project Status.” momentjs.com. https://momentjs.com/docs/

  11. npm. “@js-temporal/polyfill.” npmjs.com. https://www.npmjs.com/package/@js-temporal/polyfill

  12. Microsoft. “Announcing TypeScript 6.0 RC.” TypeScript Blog, March 6, 2026. https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-rc/

Enjoyed this article?

Stay updated with our latest insights on AI and technology.