Convert a Time Between Two Timezones in JavaScript

To convert a time between zones, build a Temporal.ZonedDateTime in the source zone and call .withTimeZone(targetZone) — same instant, new wall clock. Part of Working with ZonedDateTime Objects.

Why this scenario is tricky

"3pm in New York, what time in London?" is not offset addition — offsets change with DST and the two zones do not shift on the same day. The correct operation is to anchor the source wall time to an instant, then read that same instant's wall clock in the target zone, which is exactly what withTimeZone does.

Re-project the instant, don't add offsetsFixed offset math breaks across DSTRe-project the instant, don't add offsetsadd (targetOffset - srcOffset)wrong when DST differszdt.withTimeZone(target)same instant, new clockwithTimeZone keeps the absolute moment and recomputes the wall clock.

Minimal working solution

import { Temporal } from '@js-temporal/polyfill';
const ny = Temporal.ZonedDateTime.from('2024-03-15T15:00:00[America/New_York]');
const london = ny.withTimeZone('Europe/London');
console.log(london.toString()); // same instant, London wall clock

Re-project the instantwithTimeZone changes only the clock faceRe-project the instantNY 15:00withTimeZone('London')London time

Full production version

import { Temporal } from '@js-temporal/polyfill';
function convertZone(wall: string, from: string, to: string): Temporal.ZonedDateTime {
  // Anchor the wall time in the source zone, then re-project.
  return Temporal.PlainDateTime.from(wall).toZonedDateTime(from).withTimeZone(to);
}

From a wall stringAnchor in source, project to targetFrom a wall stringwall+from+totoZonedDateTime(from)withTimeZone(to)target time

Verification snippet

Convert Between Timezones assertionsKey cases assert correctlyAssertions that prove the edge caseNY 15:00 → London20:00 (varies by DST)same instantepoch equalDST-mismatched datestill correctround-triporiginal

Common pitfalls

Convert Between Timezones pitfallsCommon mistakes and their fixesWrongRightadd a fixed offsetDST-mismatched days wrongwithTimeZone(target)instant preservedparse without a zonehost-zone anchoranchor in source zonecorrect instant

Frequently Asked Questions

How do I convert a time from one time zone to another?

Build a Temporal.ZonedDateTime in the source zone and call withTimeZone(targetZone). It keeps the same absolute instant and recomputes the wall-clock time for the target zone, correctly accounting for each zone's DST.

Why can't I just add the offset difference between two zones?

Because offsets change with daylight saving and the two zones rarely switch on the same date. A fixed offset gives the wrong answer for part of the year; re-projecting the instant with withTimeZone always uses each zone's rules for that moment.