{"id":283,"library":"pytz","title":"pytz","description":"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.","status":"maintenance","version":"2026.1.post1","language":"python","source_language":"en","source_url":"https://github.com/stub42/pytz","tags":["datetime","timezone","tzinfo","iana","olson","dst","time","utc"],"install":[{"cmd":"pip install pytz","lang":"bash","label":"pip (legacy/compatibility)"},{"cmd":"pip install tzdata","lang":"bash","label":"Preferred stdlib alternative (Python 3.9+): tzdata for zoneinfo"}],"dependencies":[],"imports":[{"note":"Returns a pytz tzinfo object; must be used with .localize() — NOT with datetime(..., tzinfo=tz)","symbol":"timezone","correct":"from pytz import timezone"},{"note":"pytz.utc, pytz.UTC, and pytz.timezone('UTC') are all the same singleton; 'GMT' is a different object and will not compare equal","symbol":"utc / UTC","correct":"import pytz; tz = pytz.utc"},{"note":"all_timezones is the exhaustive IANA list; common_timezones omits deprecated/historical zones","symbol":"all_timezones / common_timezones","correct":"from pytz import all_timezones, common_timezones"},{"note":"Raised by timezone() for unrecognised IANA keys; also importable directly as pytz.exceptions.UnknownTimeZoneError","symbol":"UnknownTimeZoneError","correct":"from pytz.exceptions import UnknownTimeZoneError"}],"quickstart":{"code":"from datetime import datetime, timedelta\nimport pytz\n\n# --- Correct: build a UTC-aware datetime ---\nutc = pytz.utc\nutc_dt = datetime(2024, 3, 10, 7, 0, 0, tzinfo=utc)\nprint(\"UTC:\", utc_dt)\n\n# --- Correct: convert UTC -> local via astimezone ---\neastern = pytz.timezone('US/Eastern')\nloc_dt = utc_dt.astimezone(eastern)\nprint(\"Eastern:\", loc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))\n\n# --- Correct: localize a naive datetime ---\nnaive = datetime(2024, 11, 3, 1, 30)          # ambiguous wall-clock time\naware = eastern.localize(naive, is_dst=True)   # explicitly choose EDT side\nprint(\"Localized (EDT):\", aware)\n\n# --- Correct: arithmetic on local times MUST be followed by normalize ---\nbefore_dst_end = eastern.localize(datetime(2024, 11, 3, 1, 50))\nresult = eastern.normalize(before_dst_end + timedelta(minutes=20))\nprint(\"After normalize:\", result.strftime('%Y-%m-%d %H:%M:%S %Z%z'))\n\n# --- WRONG (do not do this) ---\n# wrong = datetime(2024, 11, 3, 1, 30, tzinfo=eastern)  # returns LMT, not EST/EDT!\n\n# --- Preferred modern alternative (Python 3.9+) ---\n# from zoneinfo import ZoneInfo\n# aware_modern = datetime(2024, 11, 3, 1, 30, tzinfo=ZoneInfo('US/Eastern'))\n","lang":"python","description":"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."},"warnings":[{"fix":"Always use tz.localize(naive_dt) to attach a pytz timezone to a naive datetime. Only pytz.utc is safe to pass directly to the constructor.","message":"Do NOT pass a pytz timezone directly to the datetime constructor via tzinfo=. For non-UTC zones this silently attaches the zone's historical LMT (Local Mean Time) offset, not the correct current offset, producing wrong results with a 50% chance of being off by an hour around DST transitions.","severity":"breaking","affected_versions":"all"},{"fix":"Wrap every arithmetic result with tz.normalize(result) to correct the offset. Or work exclusively in UTC and convert only for display.","message":"After any timedelta arithmetic on a pytz-aware local datetime, the UTC offset can become stale if the operation crossed a DST boundary. The offset is not automatically recalculated.","severity":"breaking","affected_versions":"all"},{"fix":"New code: use 'from zoneinfo import ZoneInfo' with 'pip install tzdata'. For gradual migration use the pytz-deprecation-shim package.","message":"The pytz maintainer and PyPI page explicitly state that projects on Python 3.9+ should use stdlib zoneinfo (PEP 615) + tzdata instead. pytz receives no new features; only IANA DB updates are applied.","severity":"deprecated","affected_versions":"all (Python 3.9+)"},{"fix":"Standardise on pytz.utc throughout pytz code, or use datetime.timezone.utc when mixing with stdlib. Never assume UTC aliases are interchangeable.","message":"pytz.utc / pytz.UTC is NOT the same object as pytz.timezone('GMT'), pytz.timezone('Greenwich'), or datetime.timezone.utc. Identity/equality checks between these will return False.","severity":"gotcha","affected_versions":"all"},{"fix":"Check dt.tzinfo is None before calling localize(). For already-aware datetimes use astimezone() to convert zones.","message":"localize() raises ValueError if the datetime already has tzinfo set. Calling localize() on an already-aware datetime is a common mistake when re-processing data.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass is_dst=None to localize() in production scheduling code so ambiguous or non-existent wall-clock times raise an exception rather than silently producing a wrong result.","message":"DST disambiguation via is_dst=None raises pytz.exceptions.AmbiguousTimeError or NonExistentTimeError instead of silently picking one, but only if you opt in. The default (is_dst=False) silently chooses standard time, which may surprise callers.","severity":"gotcha","affected_versions":"all"},{"fix":"When interfacing with PEP 495-aware code, convert: use zoneinfo.ZoneInfo(str(pytz_zone)) to obtain an equivalent stdlib zone object.","message":"pytz timezone objects are not compatible with the standard Python tzinfo interface expected by PEP 495 consumers (fold attribute). Passing pytz zones to libraries expecting stdlib-compatible tzinfo (e.g. Django 4.0+ defaults, zoneinfo consumers) can produce incorrect offsets.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T12:49:41.278Z","next_check":"2026-06-26T00:00:00.000Z","problems":[],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.6,"disk_size":"20.6M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.6,"disk_size":"21M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.9,"disk_size":"22.4M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.9,"disk_size":"23M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.5,"disk_size":"14.3M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.5,"disk_size":"15M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"13.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.5,"disk_size":"14M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.4,"disk_size":"20.1M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.4,"disk_size":"21M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}