zoneinfo reference¶
Quick reference for the zoneinfo module (Python 3.9+). For the underlying concepts see the time zones notebook.
Importing¶
ZoneInfo is the class you attach to datetimes. available_timezones() returns the full set of IANA zone names as a set[str].
Building a ZoneInfo¶
ZoneInfo("UTC")
ZoneInfo("Europe/London")
ZoneInfo("America/New_York")
ZoneInfo("Asia/Tokyo")
ZoneInfo("Australia/Sydney")
ZoneInfo("Pacific/Auckland")
Names use the IANA Continent/City form. The list of valid names is platform-dependent — it comes from your system's tzdata database (or the tzdata pip package as a fallback on Windows).
Common zone names¶
| Region | Name |
|---|---|
| UTC | UTC |
| London (and most of UK/Ireland) | Europe/London |
| Paris/Berlin/Madrid | Europe/Paris, Europe/Berlin, Europe/Madrid |
| New York | America/New_York |
| Los Angeles | America/Los_Angeles |
| Chicago | America/Chicago |
| Toronto | America/Toronto |
| São Paulo | America/Sao_Paulo |
| Tokyo | Asia/Tokyo |
| Shanghai/Beijing | Asia/Shanghai |
| Singapore | Asia/Singapore |
| Kolkata (India) | Asia/Kolkata |
| Dubai | Asia/Dubai |
| Sydney | Australia/Sydney |
| Auckland | Pacific/Auckland |
| Johannesburg | Africa/Johannesburg |
| Cairo | Africa/Cairo |
Never use abbreviations like "EST", "PST", "BST" — they're ambiguous (EST means something different in the US and Australia, for instance).
Attaching to a datetime¶
from datetime import datetime
from zoneinfo import ZoneInfo
london = ZoneInfo("Europe/London")
# At construction
dt = datetime(2026, 4, 21, 14, 30, tzinfo=london)
# Or attach to a naive datetime (assumes the naive value is *already* in that zone)
naive = datetime(2026, 4, 21, 14, 30)
aware = naive.replace(tzinfo=london)
replace(tzinfo=...) attaches the zone without changing the wall-clock values — use it when the value is already in the target zone and just lacks the metadata. Use .astimezone(target) to convert between zones.
Converting between zones¶
utc = ZoneInfo("UTC")
tokyo = ZoneInfo("Asia/Tokyo")
moment = datetime(2026, 4, 21, 14, 30, tzinfo=utc)
print(moment.astimezone(tokyo)) # 2026-04-21 23:30:00+09:00
.astimezone(target) preserves the absolute instant — only the wall-clock representation changes.
Getting the current time¶
datetime.now(tz=ZoneInfo("UTC")) # aware, UTC
datetime.now(tz=ZoneInfo("Europe/London")) # aware, London
Never datetime.now() (naive, local) or datetime.utcnow() (naive but UTC — the worst of both worlds).
Inspecting a zone¶
Given a ZoneInfo and an aware datetime:
dt = datetime(2026, 7, 15, 12, 0, tzinfo=ZoneInfo("Europe/London"))
dt.utcoffset() # timedelta(seconds=3600) — BST in July
dt.tzname() # 'BST'
dt.dst() # timedelta(seconds=3600) — 1 hour of DST in effect
Same inspection in January would give 0:00:00, 'GMT', and 0:00:00.
Enumerating all zones¶
from zoneinfo import available_timezones
all_zones = available_timezones()
print(len(all_zones)) # ~600 typically
print(sorted(all_zones)[:10]) # sample
Useful for dropdowns or validation. Filter by prefix (Europe/, America/) if you want a region-specific list.
DST transitions — the fold attribute¶
For ambiguous wall-clock times (the hour that happens twice in autumn), the fold attribute disambiguates: fold=0 picks the first occurrence, fold=1 picks the second.
london = ZoneInfo("Europe/London")
# 2026-10-25 01:30 happens twice
before = datetime(2026, 10, 25, 1, 30, fold=0, tzinfo=london) # BST
after = datetime(2026, 10, 25, 1, 30, fold=1, tzinfo=london) # GMT
print(before.utcoffset()) # 1:00:00
print(after.utcoffset()) # 0:00:00
For non-existent times (the spring-forward gap), zoneinfo returns whatever the system would show for that moment — fold picks between the two possible offset choices. Most application code doesn't care; if yours does, the Python docs have more detail.
ZoneInfo versus datetime.timezone¶
datetime.timezone(timedelta(hours=1)) gives a fixed-offset zone — no DST, no zone name, just "+01:00". Useful for representing an ISO 8601 offset without a full IANA zone, but not a replacement for ZoneInfo when DST matters.
from datetime import timezone, timedelta
fixed = timezone(timedelta(hours=1)) # UTC+01:00, no DST rules
ZoneInfo("UTC") and timezone.utc are functionally equivalent for UTC.
Errors¶
| Error | Cause |
|---|---|
ZoneInfoNotFoundError |
Name isn't in the tzdata database (typo, or missing tzdata package on Windows) |
ValueError: fold must be 0 or 1 |
Passed something else to fold |
Catch ZoneInfoNotFoundError if you're parsing zone names from user input.