UTC, epoch time, and why neither one has a timezone
The Unix epoch counts seconds since 1970-01-01T00:00:00Z — a fixed instant
on the UTC timeline. Every epoch timestamp is that count, and nothing more: no zone is
embedded in it, and none can be recovered from it later. When a system stores
1786795200, it has stored one specific moment in the history of the
universe, not a claim about what a clock on any particular wall read at that moment.
"Converting to a timezone" therefore never changes which instant you're looking at — it only changes how that instant is displayed. Local time is UTC plus whatever offset the chosen zone happens to be running at on that date.
How to convert UTC to local time
The arithmetic is one line: local time = UTC + offset. The offset is
positive for zones east of UTC and negative for zones west of it — Asia/Tokyo
runs UTC+09:00, so 00:00 UTC is already 09:00 the same day in Tokyo, while
America/Los_Angeles runs UTC-08:00 (or -07:00
during daylight saving), so 00:00 UTC is still 16:00 or 17:00 the previous day there.
The complication is that the offset itself is not fixed for most zones. Roughly forty percent of the world's population lives somewhere that shifts its clocks for daylight saving time, and the shift dates differ by country — so the correct offset depends on the exact date you're converting, not just the zone name. That's why a hand-maintained offset table drifts out of date twice a year; a converter needs the full tz-database rules, not a snapshot of them.
Converting epoch time in your own code
Intl.DateTimeFormat carries the same IANA tz database your browser uses for
every zone, DST rules included — no lookup table to bundle or update:
// JavaScript — a Date is always a UTC instant internally
const instant = new Date(epochSeconds * 1000)
const tokyoTime = instant.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' })
// The offset itself, correct for this specific date (DST-aware)
const offset = new Intl.DateTimeFormat('en-US', {
timeZone: 'Asia/Tokyo',
timeZoneName: 'longOffset',
}).formatToParts(instant).find((p) => p.type === 'timeZoneName').value
// "GMT+09:00"
# Python — zoneinfo ships the same tz database
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
instant = datetime.fromtimestamp(epoch_seconds, tz=timezone.utc)
tokyo_time = instant.astimezone(ZoneInfo('Asia/Tokyo'))
Both snippets assume you already have a correct epoch value to start from — getting one
is its own small trap, covered in full for
JavaScript's millisecond Date API and
for Python's datetime and time
modules, which count in seconds.
Common timezone offsets
Standard-time offsets for a handful of frequently converted zones. Zones marked with two abbreviations shift by one hour for part of the year; the exact transition dates vary by country, so treat this table as a starting point, not a substitute for a DST-aware conversion.
| Zone | Abbreviation | Standard offset | DST offset |
|---|---|---|---|
| UTC | UTC | UTC+00:00 | — |
| Europe/London | GMT / BST | UTC+00:00 | UTC+01:00 |
| Europe/Paris, Europe/Berlin | CET / CEST | UTC+01:00 | UTC+02:00 |
| America/New_York | EST / EDT | UTC-05:00 | UTC-04:00 |
| America/Chicago | CST / CDT | UTC-06:00 | UTC-05:00 |
| America/Denver | MST / MDT | UTC-07:00 | UTC-06:00 |
| America/Los_Angeles | PST / PDT | UTC-08:00 | UTC-07:00 |
| Asia/Kolkata | IST | UTC+05:30 | — |
| Asia/Shanghai | CST | UTC+08:00 | — |
| Asia/Tokyo | JST | UTC+09:00 | — |
| Australia/Sydney | AEST / AEDT | UTC+10:00 | UTC+11:00 |
Frequently asked questions
Does epoch (Unix) time have a timezone?
No. Epoch time counts seconds since 1970-01-01T00:00:00 UTC, a single
absolute instant with no zone attached. Converting it to a timezone means picking a
zone's offset and rendering that same instant as that zone's wall-clock time — the
underlying instant never changes.
How do I convert UTC to local time?
Add the target zone's current offset to the UTC time: local time equals UTC plus the offset. The offset itself depends on the date, because zones that observe daylight saving time use a different offset for part of the year.
What is the difference between GMT and UTC?
For everyday conversion, none — both sit at offset zero. Technically GMT is a specific timezone (the one the UK uses in winter), while UTC is the time standard other zones are defined as an offset from. GMT can drift by leap seconds in principle; UTC is what clocks, servers, and the epoch are actually defined against.
Why do some timezones have 30 or 45 minute offsets?
Political and historical choices, not geography. India (UTC+05:30),
Newfoundland (UTC-03:30), and Nepal (UTC+05:45) all picked a
half- or quarter-hour offset rather than aligning to the nearest whole hour.
Does this tool account for daylight saving time?
Yes. It reads offsets from the IANA tz database via the browser's Intl API,
which encodes each zone's historical and current DST rules, so the offset shown is
correct for the specific date entered rather than just the zone's standard-time offset.
Where to go next
An offset written into the timestamp itself — the +05:30 on the end of an
ISO 8601 or RFC 3339 string — is the other place zones and
epoch time meet, and dropping it is the most common way a converted instant silently
moves by a few hours. If you only need a zone rendering of right now,
the live Unix clock is the shorter path.