XSCREENSAVER / 3D PIPES

[readonly] markdown buffer

Using Temporal

Feb 17, 2026 · 6 min read

JavaScript Date mixes several ideas into one mutable object: an exact instant, a local clock reading, a calendar date and the runtime's time zone. Temporal separates them.

That type split is the real improvement. Here are the seven production problems it solves.

1. Repeated local times

When daylight saving time ends, a local time such as 01:30 can occur twice. Temporal makes the policy explicit:

const first = Temporal.ZonedDateTime.from(
  { timeZone: 'America/New_York', year: 2026, month: 11, day: 1, hour: 1, minute: 30 },
  { disambiguation: 'earlier' }
);

const second = Temporal.ZonedDateTime.from(
  { timeZone: 'America/New_York', year: 2026, month: 11, day: 1, hour: 1, minute: 30 },
  { disambiguation: 'later' }
);

The choice belongs to the business process, not an invisible parser default.

traceview://dispatch-console/ambiguousinteractive

Bob's International Delivery

Dispatch Console

LiveOps: LON-02

Repeated 01:30 in New York.

2. Missing local times

When clocks move forward, some local times never occur. High-impact scheduling normally wants reject so an operator resolves the intent:

Temporal.ZonedDateTime.from(
  { timeZone: 'America/New_York', year: 2026, month: 3, day: 8, hour: 2, minute: 30 },
  { disambiguation: 'reject' }
); // throws

earlier, later and compatible are available when the product has a documented shift policy.

traceview://dispatch-console/impossibleinteractive

Bob's International Delivery

Dispatch Console

LiveOps: LON-02

A local time that does not exist.

3. Business time zones

new Date('2026-10-14T09:00') interprets the value in the runtime's local zone. A London dispatcher entering a customer's 09:00 New York delivery can therefore create the wrong instant.

Temporal keeps the zone with the civil intent, then produces one canonical instant:

const delivery = Temporal.ZonedDateTime.from({
  timeZone: 'America/New_York',
  year: 2026,
  month: 10,
  day: 14,
  hour: 9
});

const instant = delivery.toInstant();
const londonView = instant.toZonedDateTimeISO('Europe/London');

Store the instant for the timeline. Keep the named zone and policy when the original civil intent matters.

traceview://dispatch-console/timezoneinteractive

Bob's International Delivery

Dispatch Console

LiveOps: LON-02

A New York slot entered by a London dispatcher.

4. Immutable arithmetic

Date setters mutate shared objects. Temporal operations return new values:

const scheduled = Temporal.PlainDateTime.from('2026-02-17T09:30');
const nextWeek = scheduled.add({ weeks: 1 });
// scheduled is unchanged

That removes a common source of hidden side effects in helpers, caches and retry logic.

5. Historical zone rules

An offset describes one moment; it does not describe a region's rules. Samoa crossed the International Date Line in 2011 and skipped a civil day. Named IANA zones allow the runtime's time-zone data to represent changes like that.

traceview://dispatch-console/historyinteractive

Bob's International Delivery

Dispatch Console

LiveOps: LON-02

Samoa's 2011 date-line shift.

6. Calendar-only values

A due date is not necessarily a midnight instant. Use Temporal.PlainDate for birthdays, billing days and contractual dates so a time-zone conversion cannot move them to the previous day.

Calendars are also separate from zones:

const isoDate = Temporal.PlainDate.from('2026-02-17');
const hebrewDate = isoDate.withCalendar('hebrew');
const japaneseDate = isoDate.withCalendar('japanese');

The calendar changes how the date is labelled, not which day it represents.

7. Strict parsing

Temporal accepts defined formats rather than relying on Date.parse()'s broad compatibility behaviour.

Temporal.PlainDate.from('2026-02-17'); // valid
Temporal.PlainDate.from('02/17/2026'); // throws

Strict boundaries are useful: validate and normalise input once rather than letting environment-dependent parsing leak into scheduling logic.

Choose the type you mean

  • Temporal.Instant — one exact point on the timeline
  • Temporal.ZonedDateTime — civil time in a named zone
  • Temporal.PlainDate — a calendar date without a time or zone
  • Temporal.Duration — an amount used for explicit arithmetic

Migrate the riskiest edges first: ambiguous input, cross-zone conversion, mutable helpers and date-only values. Keep Date at legacy integration boundaries and convert on entry.

The value of Temporal is not a nicer date object. It is making invalid combinations difficult to express and forcing time-zone policy into the code where reviewers can see it.

Playground

traceview://temporal-playgroundinteractive

Temporal Playground

Full Temporal playground.