Skip to main content
TF
By Rohit V.8 min readArticle

The Temporal API Is in Chrome Now: What Changes

TF
ToolsFuel Team
Web development tools & tips
Row of clocks showing different time zones

Photo by Unsplash on Unsplash

Short Answer

> Quick answer: Temporal reached TC39 Stage 4 in March 2026 and is part of ECMAScript 2026. It ships natively in Chrome 144, Firefox 139 and Edge 144. Safari hasn't shipped it in stable yet, so it sits behind a flag in Technology Preview with stable support expected later in 2026. Until then you need `@js-temporal/polyfill` if Safari users matter to you.

It replaces `Date` with a set of immutable, purpose built types: `Temporal.Instant` for an exact moment, `Temporal.ZonedDateTime` for a moment in a named zone, and `Temporal.PlainDate` for a calendar date with no time attached. Months are finally one based, so January is 1.

What Was Actually Wrong With Date

`Date` shipped in 1995, copied from an early version of Java, and got frozen almost immediately. Nearly every complaint about it traces back to that.

It's a timestamp wearing a calendar costume. Internally a `Date` is a single number of milliseconds since the epoch, but the API pretends it also knows about years, months and days, and it resolves that pretence using whatever time zone the machine happens to be set to. Two users running identical code get different answers.


Then there's the mutation problem. `d.setDate(d.getDate() + 1)` changes the object in place, so any other reference to it silently moves too. I've lost more time to that than to any other date bug, usually in a loop where the same object gets reused.


Months counted from zero while days counted from one. Parsing anything that isn't strict ISO 8601 was left up to the engine, which is why `new Date('2026-08-10')` and `new Date('08/10/2026')` can land on different days. And there was no way to represent a date without a time, even though a birthday or an invoice date has no business carrying midnight in a time zone.


Every date library that ever got popular existed to paper over that list. Temporal removes the reason they existed.

The Types You Will Actually Use

There are more Temporal types than most people need. Three cover the majority of real code.

`Temporal.Instant` is an exact point on the timeline with nanosecond precision and no calendar attached. Use it for anything you'd store as a timestamp: created at, logged at, expires at. It's the honest version of what `Date` was pretending to be.


`Temporal.ZonedDateTime` is an instant plus a named IANA time zone, so it knows that 9am in `Asia/Kolkata` is a different moment from 9am in `America/New_York`. This is what you want for meetings, schedules and anything a human reads off a clock.


`Temporal.PlainDate` is a calendar date with no time and no zone. A birthday. A due date. Things that are the same date everywhere in the world. There's also `PlainTime`, `PlainDateTime`, `PlainYearMonth` and `PlainMonthDay` for narrower cases, plus `Temporal.Duration` for spans of time.


Everything is immutable. `date.add({ days: 1 })` returns a new object and leaves the original alone, which quietly kills an entire category of bug. If you handle raw epoch values a lot, our
unix timestamp converter is handy for sanity checking what an `Instant` actually holds.

Where It Ships Today

Firefox got there first, shipping Temporal by default in Firefox 139 back in May 2025, well ahead of the standard being finalised.

Chrome followed with Chrome 144 in January 2026, and Edge picked it up in the same version since it shares the engine. Between those three you cover most desktop and Android traffic already.


Safari is the gap. It exists in Technology Preview behind a flag but hasn't reached a stable release, with support expected later in 2026. On iOS every browser uses the Safari engine, so that gap covers all iPhone traffic regardless of which browser icon your users tap.


Server side, anything running a recent V8 has it, which covers current Node and Deno and Bun releases. That matters because it means you can start on the backend immediately and let the frontend catch up later, and backend code is usually where the painful date logic lives anyway. Storing an `Instant` rather than a loosely parsed string removes a whole class of reporting bug before it reaches a browser.


The practical read is that Temporal is safe for internal tools, admin panels and anything Node based right now, and needs the polyfill for a public site with iOS users. The
MDN Temporal reference tracks the per method support tables if you want to check something specific.

Rewriting the Code You Write Most

Most date code in a normal codebase is four operations, and all four get shorter.

Getting the current moment goes from `new Date()` to `Temporal.Now.instant()` for a timestamp, or `Temporal.Now.zonedDateTimeISO()` when you need the user's zone. Being forced to say which one you mean is the point.


Adding time changes from the mutation dance to `plainDate.add({ months: 1 })`, and it handles the awkward cases sensibly. Adding a month to 31 January gives you 28 or 29 February rather than rolling into March, which is what people almost always want and almost never got.


Comparing two dates stops involving `getTime()`. You get `Temporal.PlainDate.compare(a, b)` returning the usual negative, zero or positive, and `a.equals(b)` for a straight equality check that doesn't accidentally compare object identity.


Differences come back as a `Duration` rather than a raw millisecond count, so `a.until(b, { largestUnit: 'day' })` gives you something you can read without dividing by 86400000 and hoping. That constant appearing in a codebase has always been a sign something was wrong.

Time Zones Stop Being Guesswork

This is the part that earns the migration on its own.

`Date` only ever knew two zones, the machine's local zone and UTC. Anything else meant a library or manual offset arithmetic, and offsets are not zones. An offset of plus five thirty is a number, while `Asia/Kolkata` is a rule set that knows its own history of changes.


Daylight saving is where that distinction bites. A meeting set for 9am next March in `America/New_York` is a different number of hours from now depending on whether the clocks have moved, and only a zone aware type gets that right. `ZonedDateTime` carries the zone with the value so the arithmetic stays correct across the transition.


Temporal also handles the genuinely strange cases explicitly rather than silently. Times that don't exist because the clocks jumped forward, and times that happen twice because they went back, both get a defined disambiguation option instead of whatever the engine felt like doing.


I've shipped bugs from treating an offset as a zone more than once, and the fix was always the same realisation: the offset was correct on the day I tested and wrong six months later.

Should You Migrate Yet

Depends entirely on whether Safari is in your traffic.

For a Node service, a build script, an internal dashboard or a Chrome extension, there's no reason to wait. The API is standardised, it's in ECMAScript 2026, and the behaviour won't shift under you now that it's at Stage 4.


For a public web app, add `@js-temporal/polyfill` and write Temporal code today. The polyfill is a real cost in bundle size, so weigh it against whatever date library you're currently shipping. Swapping a heavy library for the polyfill is usually a wash now and a win the moment Safari ships and you drop it.


What I wouldn't do is a big bang rewrite of working date code. New code in Temporal, old code left alone until you're touching it anyway, is the cheap path. Mixing both in one codebase is fine, and `Temporal.Instant.fromEpochMilliseconds(date.getTime())` bridges an existing `Date` when you need to cross over.


If you're doing that migration alongside API work, our guide on
reading JSON from an API with fetch covers the parsing side, since serialised dates crossing a network boundary are where most of these bugs are born.

Frequently Asked Questions

Is the Temporal API production ready in 2026?

Yes for Chrome, Firefox, Edge and Node. It reached TC39 Stage 4 in March 2026 and is part of ECMAScript 2026, so the behaviour is stable. Safari hasn't shipped it in a stable release yet, so public sites with iOS traffic still need the polyfill.

Which browsers support Temporal natively?

Firefox 139 shipped it first in May 2025, then Chrome 144 in January 2026, with Edge 144 following since it shares the engine. Safari has it in Technology Preview behind a flag with stable support expected later in 2026.

Does Temporal replace the Date object completely?

It's designed to, but Date isn't going anywhere for backward compatibility. You can mix them and bridge with Temporal.Instant.fromEpochMilliseconds(date.getTime()) where old code hands you a Date.

Are Temporal months still zero indexed?

No, and this is one of the better fixes. Temporal months start at 1, so January is 1 rather than 0. If you're checking raw epoch values while migrating, our [unix timestamp converter](/tools/unix-timestamp-converter) makes it quick.

What is the difference between Instant and ZonedDateTime?

Instant is an exact point on the timeline with no calendar or zone, which suits stored timestamps. ZonedDateTime is that same moment paired with a named IANA zone, which is what you need for anything a person reads off a clock.

Do I still need a date library like date-fns or Luxon?

For new code, mostly no. Those libraries existed to work around Date's design, and Temporal covers formatting, arithmetic, comparison and time zones natively. Formatting for display still goes through Intl.DateTimeFormat.

Try ToolsFuel

23+ free online tools for developers, designers, and everyone. No signup required.

Browse All Tools