Codectionary / Developer documentation / Python

Time zones with zoneinfo

Represent regional time zones and convert aware datetimes without hardcoding daylight-saving offsets.

How it works

zoneinfo, available from Python 3.9, reads IANA time-zone rules. A named zone can use different UTC offsets on different dates; a fixed offset is not equivalent to a regional zone.

These examples require available IANA data. Python uses system data or the separately installed tzdata package; some Windows installations need python -m pip install tzdata. Missing data raises ZoneInfoNotFoundError. Run these examples in a local Python environment if the browser runtime lacks zoneinfo or its data.

Limitations and practical choices

Use aware datetimes and UTC when identifying an instant. replace(tzinfo=...) attaches an interpretation; it does not convert an existing instant.

Local clock times can repeat or be skipped around daylight-saving transitions. fold distinguishes the two occurrences of a repeated time; applications still need a policy for ambiguous or nonexistent user-entered times.

Try it yourself

Convert the same UTC hour in January and July to London time. Then explain why storing only a local hour without date and zone is insufficient.

Syntax

from zoneinfo import ZoneInfo
local = instant.astimezone(ZoneInfo("Europe/London"))

Examples

Convert a winter instant

Translate a known UTC instant into regional time.

from datetime import datetime, timezone
from zoneinfo import ZoneInfo
instant = datetime(2024, 1, 15, 12, tzinfo=timezone.utc)
local = instant.astimezone(ZoneInfo("Europe/London"))
print(local.isoformat())
  1. The source datetime explicitly identifies noon UTC. astimezone preserves that instant while expressing it under London’s rules.
  2. The January date has a zero UTC offset, so the displayed hour remains twelve. isoformat includes the offset rather than hiding it.
  3. Use this when presenting stored UTC timestamps to a regional audience. IANA data must be installed.
  4. Expected output: 2024-01-15T12:00:00+00:00

Account for summer time

Use the rules for a different date rather than a constant offset.

from datetime import datetime, timezone
from zoneinfo import ZoneInfo
instant = datetime(2024, 7, 15, 12, tzinfo=timezone.utc)
print(instant.astimezone(ZoneInfo("Europe/London")).isoformat())
  1. The UTC hour is again twelve, but London’s July offset is one hour ahead for this historical date.
  2. The conversion produces thirteen with +01:00. Adding a permanent one-hour offset would have been wrong for the winter example.
  3. Use named zones for regional schedules, and remember that governments can change future rules and time-zone data needs maintenance.
  4. Expected output: 2024-07-15T13:00:00+01:00

Distinguish a repeated hour

Identify both occurrences of a local time during a clock change.

from datetime import datetime, timezone
from zoneinfo import ZoneInfo
zone = ZoneInfo("Europe/London")
first = datetime(2024, 10, 27, 1, 30, tzinfo=zone, fold=0)
second = first.replace(fold=1)
print(first.astimezone(timezone.utc).isoformat())
print(second.astimezone(timezone.utc).isoformat())
  1. The local 01:30 occurs twice on this transition date. fold=0 chooses the earlier occurrence and fold=1 the later one.
  2. Converting both to UTC exposes the one-hour difference even though their local clock fields look identical.
  3. Ask for or define an ambiguity policy when accepting local booking times; a timezone name alone does not choose between repeated occurrences.
  4. Expected output: 2024-10-27T00:30:00+00:00 2024-10-27T01:30:00+00:00

Best practices

  • Use aware datetimes and UTC when identifying an instant. replace(tzinfo=...) attaches an interpretation; it does not convert an existing instant.
  • Local clock times can repeat or be skipped around daylight-saving transitions. fold distinguishes the two occurrences of a repeated time; applications still need a policy for ambiguous or nonexistent user-entered times.

Runtime & versions

Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Python language reference

Specifications & further reading