pytz

2026.1.post1 · maintenance · verified Sat Mar 28

pytz brings the IANA/Olson timezone database into Python, enabling accurate cross-platform timezone calculations and daylight-saving-time-aware datetime handling. Current version is 2026.1.post1, released March 2026; versions track IANA tz database releases (typically several times per year). The pytz maintainer explicitly states that projects on Python 3.9+ should prefer the stdlib zoneinfo module (PEP 615) with the tzdata package instead — pytz is now in maintenance mode for backwards compatibility only.

Warnings

Install

Imports

Quickstart

Canonical pytz usage: always store in UTC, convert to local only for display. Use localize() to attach a tz to a naive datetime; use normalize() after any arithmetic on a local datetime to fix DST offsets.

from datetime import datetime, timedelta
import pytz

# --- Correct: build a UTC-aware datetime ---
utc = pytz.utc
utc_dt = datetime(2024, 3, 10, 7, 0, 0, tzinfo=utc)
print("UTC:", utc_dt)

# --- Correct: convert UTC -> local via astimezone ---
eastern = pytz.timezone('US/Eastern')
loc_dt = utc_dt.astimezone(eastern)
print("Eastern:", loc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

# --- Correct: localize a naive datetime ---
naive = datetime(2024, 11, 3, 1, 30)          # ambiguous wall-clock time
aware = eastern.localize(naive, is_dst=True)   # explicitly choose EDT side
print("Localized (EDT):", aware)

# --- Correct: arithmetic on local times MUST be followed by normalize ---
before_dst_end = eastern.localize(datetime(2024, 11, 3, 1, 50))
result = eastern.normalize(before_dst_end + timedelta(minutes=20))
print("After normalize:", result.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

# --- WRONG (do not do this) ---
# wrong = datetime(2024, 11, 3, 1, 30, tzinfo=eastern)  # returns LMT, not EST/EDT!

# --- Preferred modern alternative (Python 3.9+) ---
# from zoneinfo import ZoneInfo
# aware_modern = datetime(2024, 11, 3, 1, 30, tzinfo=ZoneInfo('US/Eastern'))

view raw JSON →