Time Utilities

World Clock

Show current time in multiple timezones at once.

UTC
--:--:--
UTC
Beijing
--:--:--
Asia/Shanghai
Tokyo
--:--:--
Asia/Tokyo
New York
--:--:--
America/New_York
Los Angeles
--:--:--
America/Los_Angeles
London
--:--:--
Europe/London
Paris
--:--:--
Europe/Paris
Sydney
--:--:--
Australia/Sydney

What is World Clock?

World clock displays current time across multiple cities and time zones simultaneously.

Features

  • Multiple city display
  • Real-time updates
  • Customizable city list

Use Cases

  • Global team coordination
  • International business
  • Travel planning

A world clock renders one instant in several IANA time zones at once, refreshing every second so the working hours of different offices can be compared side by side. This one covers eight fixed zones, from UTC and Shanghai to London, Paris and Sydney, for standup scheduling, shift handover and checking which business day a deploy lands on.

Why the Sydney card can read 24:22:14

The formatter asks for dateStyle: 'short', timeStyle: 'medium' and hour12: false, then leaves the hour cycle to the browser's CLDR data. For en-US that resolves to h24, which numbers hours 1-24, so during the first hour after local midnight the hour field reads 24. With Sydney on UTC+11, the instant 2026-10-22T13:22:14Z prints as 10/23/26, 24:22:14 in the English interface, while the same instant under the zh-CN pattern, which is h23, prints 2026/10/23 00:22:14. Both strings are conformant, and neither is an error in this page; but 24:22:14 is not a clock reading another parser will accept, so copy the hour as 00 before pasting it anywhere. The short date diverges too: month-first with a two-digit year versus year-first.

One sample per second, shared by eight cards

The component keeps a single reactive field holding epoch milliseconds, samples Date.now() once per tick and formats all eight zones from that one value. That is why no two cards can ever disagree by a second, which is exactly what happens when each formatter reads the clock itself. The tick is a free-running setInterval of 1000 ms started when the component mounts, not aligned to wall-clock boundaries, so a digit can change up to a second after the true second boundary. Browsers throttle timers in hidden tabs, so a backgrounded page stops sampling and jumps forward on its next tick when you return to it. The instant comes from the operating system clock, never from the network: a machine running 40 seconds slow produces eight consistently slow cards, and nothing in the panel flags it. Until the first tick every cell shows --:--:--.

Offsets are implied, never printed

A card carries a translated city label, the formatted time and the raw IANA id; the numeric offset and the zone abbreviation are absent, because an offset belongs to an instant rather than to a city. To compare two cities you subtract the printed times yourself, and those differences are not constant. On 2026-10-22 the Shanghai and Paris cards are six hours apart; from 2026-10-25T01:00Z Paris falls back to UTC+1 and the gap becomes seven. London and Paris switch at that identical instant, so their mutual one-hour gap never varies, yet the London card prints 01:00 twice inside that hour - 01:59 while still on BST, then 01:00 on GMT. Sydney moved on 2026-10-03 and stays on UTC+11 until April, holding Shanghai three hours away. With no date field the tool can only show now; a proposed meeting time belongs in the timezone converter.

Worked example

All eight cards at one sampled instant

Input
2026-10-22T13:22:14Z (epoch 1792675334000)
Output
UTC 10/22/26, 13:22:14 | Shanghai 10/22/26, 21:22:14 | Tokyo 10/22/26, 22:22:14 | New York 10/22/26, 09:22:14 | Los Angeles 10/22/26, 06:22:14 | London 10/22/26, 14:22:14 | Paris 10/22/26, 15:22:14 | Sydney 10/23/26, 24:22:14

Every line is one render of the same 1792675334000 ms value, so the eight readings are mutually consistent to the second. Sydney reads the next calendar day because UTC+11 pushes 13:22 past midnight, and its hour prints as 24 rather than 00 because the English pattern uses the h24 cycle. New York is still on EDT (UTC-4) and Los Angeles on PDT (UTC-7) until 2026-11-01, so the two US cards sit three hours apart while Central Europe is already seven hours behind Shanghai.

Limits and pitfalls

  • The zone list is hard-coded to eight IANA ids in a fixed order (UTC, Asia/Shanghai, Asia/Tokyo, America/New_York, America/Los_Angeles, Europe/London, Europe/Paris, Australia/Sydney). There is no add, remove or type-ahead, so Asia/Kolkata (+05:30), Europe/Berlin and America/Chicago cannot be brought onto the screen at all.
  • It displays now and nothing else: there is no date or time input, so planning a call for next Tuesday requires the timezone converter instead.
  • Readings come from the local system clock via Date.now(), never from a network time source; a skewed or drifting machine clock skews all eight cards equally and the panel gives no warning.
  • Refresh is a free-running 1000 ms interval started at mount, unaligned to second boundaries, and hidden tabs are throttled by the browser, so a backgrounded page can display a stale second until the following tick.
  • Output is a locale-formatted string with no offset and no zone abbreviation, so it cannot be quoted as an unambiguous instant in code, logs or calendar invites.

Related tools

When it goes wrong

The card is titled Beijing, but the small line under the time reads Asia/Shanghai, so I wrote Asia/Beijing into our service config and it was rejected.

CauseThe title is a translated label (tools.worldclock.beijing, which reads Beijing in English and 北京时间 in Chinese) while the identifier is a constant string in the component. The two are not derived from one another, and IANA has no Asia/Beijing entry: the id that covers the whole of mainland China is Asia/Shanghai, one zone for one UTC+8 area.

FixCopy the third line, not the title. If the target is a Windows zone registry rather than IANA, the same area is China Standard Time; a bare UTC+8 is a fixed offset, not a zone, and would freeze the rules of whichever city you copied it from.

A colleague sits in Bengaluru. I added five and a half hours to the UTC card and got a time one calendar day off.

CauseNo card in the panel carries a half-hour offset, so UTC is the only clean base. That cell is formatted with hour12: false and no explicit hour cycle, which the English interface resolves to h24, so in the hour after midnight it prints 24:xx rather than 00:xx. Adding 5h30m to 24:xx overshoots by a full day; the Chinese interface prints 00:xx for the same instant, which is why two people doing identical arithmetic disagree.

FixRead 24:xx as 00:xx of the following day before adding, or skip the arithmetic entirely: new Date().toLocaleString("en-GB", { timeZone: "Asia/Kolkata", hour12: false }) prints the Bengaluru reading straight from any browser console.

All eight cards sit on --:--:-- and never fill in, however long I leave the page open.

CauseThe template prints that literal placeholder whenever ready is false, and ready is flipped only inside onMounted. The island is mounted with client:idle, so when the bundle is blocked - an ad blocker, a strict CSP, JavaScript disabled - the component never hydrates and the dashes stay forever. A busy main thread delays the same moment rather than replacing it.

FixAllow the page's own script and reload, then confirm hydration by watching one card change on the next second boundary. In an environment where scripts cannot run, this panel will never show a time; read the operating system clock instead.

The London card reads 14:22:14 and I still cannot tell whether the invite should say BST or GMT.

CauseThe formatter passes only timeZone, dateStyle, timeStyle and hour12; timeZoneName is omitted, so neither the abbreviation nor a signed offset reaches the card. London sits on UTC+1 for part of the year and UTC+0 for the rest, and the printed digits carry no hint of which rule is active.

FixSubtract the London cell from the UTC cell at the same tick: 0 means GMT, one hour means BST. For a value you can paste into a rule, Intl.DateTimeFormat("en-US", { timeZone: "Europe/London", timeZoneName: "longOffset" }) returns GMT+01:00 until the last Sunday of October and GMT after it.

One concrete scenario

The Wednesday reconciliation that shifts by an hour in late October

A Shanghai team reconciles with colleagues in London and Sydney every Wednesday at 09:00 Shanghai time. On 22 October that instant is 02:00 on the London card and 12:00 on the Sydney card - gaps of seven hours and three. The next week the same sentence means something else: London has fallen back to GMT while Sydney holds UTC+11, so 09:00 in Shanghai becomes 01:00 in London, an eight-hour gap, and still 12:00 in Sydney. Because all eight cells render one sampled Date.now() value, the gaps can be subtracted directly. With no date field the page only shows now, so pin the slot as 01:00Z and convert the actual date elsewhere.

Frequently Asked Questions

Why are some timezones offset by half an hour?
About 40 regions use non-whole-hour offsets: India +05:30, Iran +03:30, Nepal +05:45 (the world’s only 45-minute offset). These are historical and political choices, not geography — never assume "all timezones are whole hours" when working with South Asia.
Why prefer "Asia/Shanghai" over "UTC+8"?
A fixed offset carries no DST rules: America/New_York swings between -5 and -4 across the year, so a hard-coded UTC-5 is wrong for half the year. IANA zone names (Asia/Shanghai, America/New_York) encode the full history and rules — the correct choice for code and configuration.
How do I run meetings across continents?
Rotate the sacrifice (this quarter Asia wakes early, next quarter Europe stays late); anchor on UTC rather than one person’s local time so DST switches do not silently move the meeting; confirm everyone’s local time on the world clock, with extra care during DST transition weeks.

Content reviewed: