UTC vs GMT — What Is the Difference?

· utcfundamentals

They agree to within a second, which is why the difference is usually ignored — and exactly why it surprises people when it finally matters.

UTC and GMT display the same clock reading. They are not the same kind of thing, and conflating them causes a specific, avoidable class of bug.

The short version

GMT (Greenwich Mean Time) is a time zone. It is based on the mean solar time at the Royal Observatory in Greenwich, and it is the zone that the United Kingdom uses in winter. Countries observe GMT; it appears in legislation and on clocks.

UTC (Coordinated Universal Time) is a time standard. It is derived from International Atomic Time (TAI), kept within 0.9 seconds of the Earth’s rotation by leap seconds. No country is “on UTC” as a legal matter — UTC is the reference that every zone is defined as an offset from.

So Europe/London is a time zone that follows GMT in winter and BST in summer. UTC is the fixed reference against which both are measured.

Why the names are backwards

The abbreviation looks like it should be CUT in English or TUC in French. Neither language won: UTC was chosen precisely because it favours neither, keeping the abbreviation uniform across languages. The C stands for “Coordinated”.

Where the distinction actually bites

GMT is not a fixed offset in Britain. This is the practical trap. From late March to late October, the UK is on British Summer Time, UTC+01:00. Software that treats “GMT” as a synonym for “UTC+0” and applies it to UK users is an hour wrong for seven months of the year. Use Europe/London, which knows about BST; do not use GMT.

HTTP still says GMT. RFC 7231 mandates this format for Date and Expires headers:

Date: Sun, 10 Mar 2024 06:00:00 GMT

The GMT there is required literal text and means UTC. It is never anything else — do not parse it as a zone name.

Java’s GMT zone is UTC. TimeZone.getTimeZone("GMT") returns a fixed UTC+0 zone with no daylight saving, which is not the UK’s actual zone. ZoneId.of("Europe/London") is what you want for British local time.

POSIX TZ strings invert the sign. TZ=GMT+5 means five hours behind UTC, not ahead. This is a genuine reversal in the POSIX specification and it catches everyone once. IANA names do not have this problem.

Zone abbreviations are ambiguous in general. CST is US Central, China Standard and Cuban Standard time. IST is Indian, Irish and Israeli. Abbreviations are for display only; never parse them or store them.

What to use where

Context Use
Storing an instant Unix timestamp, or a UTC timestamp column
API interchange ISO 8601 with Z2024-03-10T06:00:00Z
HTTP headers RFC 7231 format with the literal GMT
UK local time IANA Europe/London
Displaying to users Their IANA zone, resolved at render time
Anything at all Never a bare abbreviation like GMT or CST

The leap-second footnote

Because UTC includes leap seconds and mean solar time does not, UTC and true GMT drift apart by up to 0.9 seconds before a leap second pulls them back. This has never mattered for software and, once leap seconds are abolished in 2035, the two will drift apart indefinitely — at which point “GMT” as a scientific term becomes purely historical, while remaining a perfectly good name for a British time zone.

Practical summary

Store UTC. Convert to a named IANA zone for display. Treat GMT as a legacy string that means UTC in HTTP headers and means the UK’s winter time everywhere else — and never as a substitute for a real time zone identifier.

You can see the offset for any zone, including Europe/London across its BST transitions, on the time zone pages.

Related guides