Skip to content

Instantly share code, notes, and snippets.

@yeiichi
Created March 20, 2026 01:34
Show Gist options
  • Select an option

  • Save yeiichi/d5148b5dc4972a7a0bfe2b729fd5001e to your computer and use it in GitHub Desktop.

Select an option

Save yeiichi/d5148b5dc4972a7a0bfe2b729fd5001e to your computer and use it in GitHub Desktop.
Utility helpers for working with timezone-aware datetimes
"""
datetime_util.py
Utility helpers for working with timezone-aware datetimes.
This module provides:
- Predefined, commonly used timezone constants (UTC, JST, ET, etc.)
- Convenience functions for getting the current time in specific regions
- Safe conversion utilities that enforce timezone awareness
- ISO 8601 serialization and parsing helpers
- A simple wrapper for constructing ZoneInfo instances
Design principles:
- Always prefer *aware* datetimes (naive datetimes are rejected)
- Keep APIs small, explicit, and predictable
- Use standard library only (datetime, zoneinfo)
Typical usage:
from datetime_util import now_jst, to_iso, from_iso, JST, ET
dt_jst = now_jst()
dt_et = dt_jst.astimezone(ET)
iso_str = to_iso(dt_jst)
parsed = from_iso(iso_str)
assert parsed.tzinfo is not None
Notes:
- All conversion helpers raise ValueError when given naive datetimes
- Timezones are based on IANA names via zoneinfo
- Daylight Saving Time (DST) is handled automatically by ZoneInfo
This module is intended to be a lightweight, dependency-free foundation
for consistent datetime handling across applications.
"""
from __future__ import annotations
from datetime import UTC, datetime
from zoneinfo import ZoneInfo
# ---- Public timezone constants ----
UTC_TZ = UTC
JST = ZoneInfo("Asia/Tokyo")
KST = ZoneInfo("Asia/Seoul")
CST_CN = ZoneInfo("Asia/Shanghai")
IST = ZoneInfo("Asia/Kolkata")
SGT = ZoneInfo("Asia/Singapore")
ET = ZoneInfo("America/New_York")
PT = ZoneInfo("America/Los_Angeles")
GMT = ZoneInfo("Europe/London")
CET = ZoneInfo("Europe/Paris")
__all__ = [
"UTC_TZ",
"JST",
"KST",
"CST_CN",
"IST",
"SGT",
"ET",
"PT",
"GMT",
"CET",
"now_utc",
"now_in",
"now_jst",
"now_et",
"to_timezone",
"to_iso",
"from_iso",
"tz",
]
def now_utc() -> datetime:
"""Return the current UTC datetime."""
return datetime.now(UTC_TZ)
def now_in(timezone: ZoneInfo) -> datetime:
"""Return the current datetime in the given timezone."""
return now_utc().astimezone(timezone)
def now_jst() -> datetime:
"""Return the current datetime in Asia/Tokyo."""
return now_in(JST)
def now_et() -> datetime:
"""Return the current datetime in America/New_York."""
return now_in(ET)
def to_timezone(dt: datetime, timezone: ZoneInfo) -> datetime:
"""Convert an aware datetime to another timezone.
Raises:
ValueError: If ``dt`` is naive.
"""
if dt.tzinfo is None:
raise ValueError("Naive datetime is not allowed")
return dt.astimezone(timezone)
def to_iso(dt: datetime) -> str:
"""Return an ISO 8601 string for an aware datetime.
Raises:
ValueError: If ``dt`` is naive.
"""
if dt.tzinfo is None:
raise ValueError("Naive datetime is not allowed")
return dt.isoformat()
def from_iso(value: str) -> datetime:
"""Parse an ISO 8601 string into an aware datetime.
Raises:
ValueError: If the parsed datetime is naive.
"""
dt = datetime.fromisoformat(value)
if dt.tzinfo is None:
raise ValueError("Naive datetime string is not allowed")
return dt
def tz(name: str) -> ZoneInfo:
"""Return a timezone from an IANA name.
Example:
tz("Australia/Sydney")
"""
return ZoneInfo(name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment