UTC vs GMT vs Local Time: A Developer's Guide

UTC is a standard, GMT is a time zone, and local time is a presentation choice. What each term really means, why they usually read the same, and the rules that keep time bugs out of your systems.

Published 2026-10-23

Three terms get used as if they were interchangeable — UTC, GMT and “local time” — and most of the time nothing explodes, because for everyday readings they agree. Then daylight saving changes, a server in another country logs in its own zone, or a flight lands in a different hemisphere, and the differences start costing real bugs. This guide separates the three cleanly: what each one is, why software treats UTC and GMT as synonyms, and the working rules that keep time sane. Our timestamp converter is the practical companion — it shows every instant in UTC and your local zone side by side.

Definitions first

GMT (Greenwich Mean Time) is a time zone: the civil time at the Royal Observatory in Greenwich, London, historically defined by the sun’s position. Today it survives as the name of the UK’s winter time zone (UTC+00:00) and as a label in older standards. It is a place’s time.

UTC (Coordinated Universal Time) is a time standard, not a zone. It is maintained from hundreds of atomic clocks worldwide (with occasional leap seconds to stay near solar time) and every time zone on Earth is defined as an offset from it: Tokyo is UTC+09:00, New York is UTC−05:00 or −04:00 depending on the date. UTC itself never observes daylight saving.

Local time is not a standard at all — it is a rendering: an instant, expressed in the zone of whoever is looking at it. The same moment is simultaneously 22:13 in London and 06:13 the next morning in Perth. Neither is more correct; both are presentations of one instant.

Why UTC and GMT read identically (almost always)

For civil purposes the two scales are kept within a second of each other, so a clock reading “22:13:20 GMT” and “22:13:20 UTC” name the same moment — which is why JavaScript’s toUTCString() produces a string ending in “GMT”, and HTTP headers are specified in “GMT” while meaning UTC. In code and APIs, write UTC: it’s the standard timestamps are anchored to. GMT is acceptable on user-facing labels for a UK audience. The distinction only matters in astronomy, in standards documents, and in the pedantry of colleagues — but offset errors matter everywhere, and they’re the real subject of the rest of this guide.

Offsets are not time zones

UTC+08:00 is an offset — a fixed shift. Asia/Shanghai, Australia/Perth and America/New_York are zones — named rule sets that say which offset applies on which date (including daylight-saving transitions, past and future). Two traps follow:

This is why systems store the IANA zone name (America/New_York) alongside, or instead of, any offset: the rules live in the tz database, which your OS and language runtime already ship.

One instant, four renderings

Take the single instant 1700000000 (a Unix timestamp — seconds since 1970, anchored to UTC):

ZoneLocal reading
UTCTue, 14 Nov 2023, 22:13:20
Europe/London (GMT, UTC+0 in November)Tue, 14 Nov 2023, 22:13:20
America/New_York (EST, UTC−5)Tue, 14 Nov 2023, 17:13:20
Australia/Perth (AWST, UTC+8)Wed, 15 Nov 2023, 06:13:20

One moment, four labels — including a date change. Every “the timestamp was off by a day” bug is someone treating one row of this table as if it were the instant itself.

The daylight-saving edge cases

Twice a year, zones that observe DST create local times that don’t exist and times that exist twice. When clocks spring forward, 02:30 may never occur; when they fall back, 01:30 occurs twice, an hour apart, with different offsets. Scheduling, billing and log-ordering code all meet these eventually. The defence is structural: do arithmetic on instants (timestamps/UTC), and let the zone rules handle display. If a user picks “09:00 daily in Berlin”, store the zone and the wall time, and resolve each occurrence — don’t convert once to UTC and repeat every 24 hours, or the meeting drifts an hour at each transition.

Working rules for developers

  1. Store instants, not readings. A timestamp or a UTC datetime. Never an unzoned string like 2026-10-23 09:00 — future you cannot know which row of the table it was.
  2. Transmit in ISO 8601 with an offset (2026-10-23T09:00:00+08:00) or as a timestamp. If a human chose the time in a place, keep the zone name too.
  3. Convert to local time only at display, in the viewer’s zone, at the last moment — the pattern our converter demonstrates.
  4. Do arithmetic in UTC. Durations computed across a DST boundary in local time are wrong by an hour in the interesting cases.
  5. Say UTC in code and APIs, and label user-facing times with their zone (“09:00 AWST”), never a bare “GMT” when you mean “the standard”.

Follow those and the UTC/GMT distinction returns to what it should be: a piece of terminology trivia — interesting, occasionally worth a guide, and never again the cause of a 3 a.m. incident.

Related tools

Related guides