Code should identify a time zone by its IANA name, such as America/New_York, and never by an abbreviation like CST or a fixed offset. This sheet lists the standard and summer offsets of 40 widely used zones, the 2026 clock-change dates, and the lookups that work in JavaScript, Python, PHP and the shell. It clears up one confusion: an offset such as UTC-05:00 is one moment's value, while a zone name carries the whole rule history. The sheet assumes you know what UTC is.
Offsets come from tz database release 2026b, read on 2026-01-15 (winter in the north) and 2026-07-15 (summer in the north). Where the two columns match, the zone has no clock change in 2026.
| IANA name | January offset | July offset | Notes |
|---|---|---|---|
| `UTC` | +00:00 | +00:00 | Never changes |
| `America/New_York` | -05:00 EST | -04:00 EDT | US rules |
| `America/Chicago` | -06:00 CST | -05:00 CDT | US rules |
| `America/Denver` | -07:00 MST | -06:00 MDT | US rules |
| `America/Phoenix` | -07:00 MST | -07:00 MST | No daylight saving |
| `America/Los_Angeles` | -08:00 PST | -07:00 PDT | US rules |
| `America/Anchorage` | -09:00 AKST | -08:00 AKDT | US rules |
| `Pacific/Honolulu` | -10:00 HST | -10:00 HST | No daylight saving |
| `America/Mexico_City` | -06:00 CST | -06:00 CST | No daylight saving |
| `America/Sao_Paulo` | -03:00 | -03:00 | No daylight saving |
| `America/Argentina/Buenos_Aires` | -03:00 | -03:00 | No daylight saving |
| `Europe/London` | +00:00 GMT | +01:00 BST | EU dates |
| `Europe/Dublin` | +00:00 GMT | +01:00 IST | EU dates |
| `Europe/Paris` | +01:00 CET | +02:00 CEST | EU dates |
| `Europe/Berlin` | +01:00 CET | +02:00 CEST | EU dates |
| `Europe/Athens` | +02:00 EET | +03:00 EEST | EU dates |
| `Europe/Kyiv` | +02:00 EET | +03:00 EEST | EU dates, renamed from `Europe/Kiev` |
| `Europe/Istanbul` | +03:00 | +03:00 | Permanent +03 |
| `Europe/Moscow` | +03:00 MSK | +03:00 MSK | No daylight saving |
| `Africa/Cairo` | +02:00 EET | +03:00 EEST | Own dates, see below |
| `Africa/Lagos` | +01:00 WAT | +01:00 WAT | No daylight saving |
| `Africa/Johannesburg` | +02:00 SAST | +02:00 SAST | No daylight saving |
| `Africa/Nairobi` | +03:00 EAT | +03:00 EAT | No daylight saving |
| `Asia/Dubai` | +04:00 | +04:00 | No daylight saving |
| `Asia/Tehran` | +03:30 | +03:30 | Half-hour offset |
| `Asia/Karachi` | +05:00 PKT | +05:00 PKT | No daylight saving |
| `Asia/Kolkata` | +05:30 IST | +05:30 IST | Half-hour offset |
| `Asia/Kathmandu` | +05:45 | +05:45 | 45-minute offset |
| `Asia/Dhaka` | +06:00 | +06:00 | No daylight saving |
| `Asia/Bangkok` | +07:00 | +07:00 | No daylight saving |
| `Asia/Jakarta` | +07:00 WIB | +07:00 WIB | No daylight saving |
| `Asia/Shanghai` | +08:00 CST | +08:00 CST | One zone for all of China |
| `Asia/Singapore` | +08:00 | +08:00 | No daylight saving |
| `Asia/Tokyo` | +09:00 JST | +09:00 JST | No daylight saving |
| `Asia/Seoul` | +09:00 KST | +09:00 KST | No daylight saving |
| `Australia/Perth` | +08:00 AWST | +08:00 AWST | No daylight saving |
| `Australia/Adelaide` | +10:30 ACDT | +09:30 ACST | Southern summer in January |
| `Australia/Sydney` | +11:00 AEDT | +10:00 AEST | Southern summer in January |
| `Pacific/Auckland` | +13:00 NZDT | +12:00 NZST | Southern summer in January |
| `Pacific/Chatham` | +13:45 | +12:45 | 45-minute offset |
Zones with only a numeric label, such as +03, have no widely used English abbreviation, so the database uses the offset itself.
| Region | Spring forward | Fall back | Rule |
|---|---|---|---|
| United States | Sun 2026-03-08, 02:00 local | Sun 2026-11-01, 02:00 local | Second Sunday of March, first Sunday of November |
| European Union and UK | Sun 2026-03-29, 01:00 UTC | Sun 2026-10-25, 01:00 UTC | Last Sunday of March and October |
| Egypt (`Africa/Cairo`) | Fri 2026-04-24, 00:00 local | Fri 2026-10-30, 00:00 local | Last Friday of April and October |
| Australia (Sydney, Adelaide) | Sun 2026-10-04, 02:00 standard time | Sun 2026-04-05, 03:00 summer time | First Sunday of October and April |
| New Zealand (`Pacific/Auckland`) | Sun 2026-09-27, 02:00 standard time | Sun 2026-04-05, 03:00 summer time | Last Sunday of September, first Sunday of April |
All EU countries switch at the same instant, so a Berlin clock and an Athens clock change within the same hour of UTC.
| Rule | Example |
|---|---|
| Form is `Area/Location` | `Pacific/Honolulu` |
| Areas are continents or oceans | `Africa`, `America`, `Antarctica`, `Asia`, `Atlantic`, `Australia`, `Europe`, `Indian`, `Pacific` |
| North and South America share one area | `America/Sao_Paulo` |
| Extra level for disambiguation | `America/Indiana/Petersburg` |
| ASCII letters, `.`, `-` and `_` only, no digits in new names | `America/Port-au-Prince` |
| Each part is at most 14 characters | `America/Noronha`, not `America/Fernando_de_Noronha` |
| Names are case-sensitive in the reference implementation | `Europe/Paris`, not `europe/paris` |
| Name | Actual offset |
|---|---|
| `Etc/GMT+5` | UTC-05:00 |
| `Etc/GMT-14` | UTC+14:00 |
| `Etc/UTC` | UTC+00:00 |
The sign follows the POSIX convention, where positive means west of Greenwich. Only whole hours from Etc/GMT-14 to Etc/GMT+12 exist.
const d = new Date("2026-10-05T12:00:00Z");
for (const z of ["UTC", "America/New_York", "Europe/Berlin", "Asia/Kolkata", "Asia/Tokyo", "Australia/Sydney"]) {
console.log(z.padEnd(18), d.toLocaleString("sv-SE", { timeZone: z }));
}
UTC 2026-10-05 12:00:00
America/New_York 2026-10-05 08:00:00
Europe/Berlin 2026-10-05 14:00:00
Asia/Kolkata 2026-10-05 17:30:00
Asia/Tokyo 2026-10-05 21:00:00
Australia/Sydney 2026-10-05 23:00:00
The sv-SE locale prints YYYY-MM-DD HH:mm:ss, which sorts and reads well in logs. Pass timeZone and the Date itself is never changed. The JS Intl.DateTimeFormat Playground shows the same options interactively.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
stored_utc = datetime(2026, 10, 5, 12, tzinfo=timezone.utc)
stored_zone = "Asia/Kolkata"
print(stored_utc.astimezone(ZoneInfo(stored_zone)).isoformat())
2026-10-05T17:30:00+05:30
Store the instant in UTC and, separately, the zone name the user picked. Convert only when you display. Storing just +05:30 loses the rules, so a later date in a daylight saving zone would come out wrong.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
ny = ZoneInfo("America/New_York")
print(datetime(2026, 3, 8, 2, 30, tzinfo=ny).astimezone(timezone.utc).isoformat())
print(datetime(2026, 11, 1, 1, 30, tzinfo=ny).astimezone(timezone.utc).isoformat())
print(datetime(2026, 11, 1, 1, 30, fold=1, tzinfo=ny).astimezone(timezone.utc).isoformat())
2026-03-08T07:30:00+00:00
2026-11-01T05:30:00+00:00
2026-11-01T06:30:00+00:00
At 02:00 on 2026-03-08 New York jumps to 03:00, so 02:30 never happens and Python silently maps it to 03:30 EDT. At 02:00 on 2026-11-01 the clock returns to 01:00, so 01:30 happens twice and fold picks the first (0) or second (1) one. Ask users for a zone and an exact offset, or schedule in UTC, when the hour matters.
const names = Intl.supportedValuesOf("timeZone");
console.log(names.length, names.slice(0, 3));
try {
new Date().toLocaleString("en-US", { timeZone: "America/Nowhere" });
} catch (e) {
console.log(e.name + ": " + e.message);
}
418 [ 'Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa' ]
RangeError: Invalid time zone specified: America/Nowhere
The count depends on the runtime (this run used Node.js 22). Python's zoneinfo.available_timezones() returned 498 on the test machine (the count depends on the installed tzdata) and PHP's DateTimeZone::listIdentifiers() returned 419, because each includes a different set of legacy aliases. Validate user input against the list of the runtime that will parse it.
TZ=Asia/Tokyo date -d @1791201600 '+%F %T %Z %z'
date -u -d 'TZ="America/New_York" 2026-10-05 08:00' +%FT%TZ
2026-10-05 21:00:00 JST +0900
2026-10-05T12:00:00Z
The TZ environment variable overrides the zone for a single command, and GNU date accepts an inline TZ="..." prefix in the date string. In JavaScript, Intl.DateTimeFormat().resolvedOptions().timeZone returns the zone of the current runtime.
-0600 instead of abbreviations when a program must be unambiguous. Never parse an abbreviation to find a zone.Europe/Berlin formats as GMT+2 with en-US and as MESZ with de-DE in Node.js, because en-US has no short name for Central European Summer Time. Do not compare or store the formatted label.Etc/GMT+5 is five hours behind UTC, so 2026-10-05T12:00:00Z shows as 2026-10-05T07:00:00-05:00 in Python there. Developers who read +5 as east of Greenwich are off by ten hours. Prefer a real Area/Location name for people and use Etc/GMT names only for fixed machine offsets.tzdata package updated.Europe/Kiev became Europe/Kyiv and Asia/Rangoon became Asia/Yangon. The old names still resolve in most runtimes, but a dropdown built from one runtime may not match a database built from another.-05:00 appears in America/New_York in winter and America/Chicago in summer. Saving only the offset makes it impossible to compute a future local time correctly.ZoneInfo("America/New_York") raises ZoneInfoNotFoundError unless the tzdata package from PyPI is installed. Declare it as a dependency when you ship cross-platform.timeZone and timeZoneName options and see the formatted result for any zone