Handling time in JavaScript has been a patch job for over a decade, with Moment.js covering the holes in the native Date object. Plenty of teams still pull in a 300KB library just to format a timestamp. That cost is hard to defend now that the JS Temporal API has reached Stage 4.
I have lost count of the WordPress projects I inherited where the bundle was carrying moment-timezone because the original developer did not want to fight the Date object. Moment is in maintenance mode now, and its mutable objects have caused more race conditions in my checkout scripts than I care to admit. The native replacement is Temporal.
What is the JS Temporal API?
The JS Temporal API is a modern date and time API built into the ECMAScript standard. It replaces the legacy Date object and fixes its most annoying limitations, among them zero-indexed months, where January is 0, and the total absence of time zone support. Everything in Temporal is immutable, so adding three days to a date hands you a new object instead of quietly changing the original and breaking your UI.
As of 2026 it has shipped in Chrome 144+ and Firefox 139+. Safari is still catching up, but the official polyfill weighs far less than Moment.js. If you care about WordPress performance, moving date handling to a native API is one of the cheaper wins available.
Creating and parsing dates
In Moment, creating a UTC timestamp looked simple right up to the moment you noticed you had mutated your local object. The JS Temporal API gives you a type per job: Instant for UTC, ZonedDateTime for localized time and PlainDate for things like birthdays, where the time zone is irrelevant.
// The old way (Moment)
const oldNow = moment();
const inUTC = oldNow.utc(); // Careful! oldNow is now in UTC mode too.
// The modern way (Temporal)
const now = Temporal.Now.instant();
console.log(now.toString()); // 2026-02-19T01:55:27.844Z
// Parsing an ISO string
const eventDate = Temporal.PlainDate.from('2026-03-25');
console.log(eventDate.month); // 3 (March is 3, finally!)
Date arithmetic without the gotchas
My worst war story here is a subscription plugin that charged people twice because a .add(1, 'month') call mutated a shared date object inside a loop. Temporal objects are immutable by design, so that class of bug cannot happen.
const start = Temporal.Now.plainDateTimeISO();
const nextWeek = start.add({ days: 7 });
// 'start' remains exactly what it was. No side effects.
console.log(start.toLocaleString());
console.log(nextWeek.toLocaleString());
Working out the difference between two dates is sturdier as well. Rather than handing you raw milliseconds to divide yourself, Temporal returns a Duration object.
const d1 = Temporal.PlainDate.from('2026-01-01');
const d2 = Temporal.PlainDate.from('2026-02-01');
const diff = d2.since(d1);
console.log(diff.days); // 31
Formatting through Intl
Moment needed format tokens like 'MM/DD/YYYY'. The JS Temporal API hands formatting to the built-in Intl.DateTimeFormat, so dates follow the user’s locale without you shipping a stack of localization files inside your JavaScript bundle. That removes a real chunk of JavaScript bloat.
const date = Temporal.Now.instant();
// Locale-aware formatting out of the box
console.log(date.toLocaleString('en-GB', { month: 'long', day: 'numeric' }));
// "19 February"
A real refactor: time zones
Say you are building a WooCommerce extension that shows delivery windows in several time zones. That used to mean reaching for moment-timezone. With the Temporal API the conversion is native.
function getLocalDeliveryTime(isoString, timeZone) {
const instant = Temporal.Instant.from(isoString);
const zoned = instant.toZonedDateTimeISO(timeZone);
return zoned.toLocaleString(undefined, {
timeZoneName: 'short',
hour: 'numeric',
minute: '2-digit'
});
}
// Example: Mar 5, 2026, 3:00 PM EST converted to London time
const londonTime = getLocalDeliveryTime('2026-03-05T15:00-05:00', 'Europe/London');
console.log(londonTime); // "8:00 PM GMT"
If this JS Temporal API work is eating your dev hours, I can take it on. I have been wrestling with WordPress since the 4.x days.
Stop paying the Moment tax
Moment.js was the right tool for a web where browsers were weak and bundles were small. That era is behind us, and shipping a legacy library now costs more than it saves. The JS Temporal API covers everything Moment did, and then some, without the 1MB of overhead. Add the polyfill now and delete the import once your target browsers all support it natively.