Skip to content
GreenSnippets

Parse and format ISO 8601 dates in UTC

Convert ISO timestamps to timezone-aware UTC datetimes and back, avoiding naive datetime bugs.

Python
from datetime import datetime, timezone


def parse_utc(text):
    value = datetime.fromisoformat(text.replace("Z", "+00:00"))
    if value.tzinfo is None:
        value = value.replace(tzinfo=timezone.utc)
    return value.astimezone(timezone.utc)


def to_iso_utc(value):
    return value.astimezone(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z")

Example / expected output

Output
parse_utc("2025-03-01T12:00:00+02:00")  # 2025-03-01 10:00:00+00:00
to_iso_utc(parse_utc("2025-03-01T12:00:00+02:00"))  # '2025-03-01T10:00:00Z'

How it works

Store and exchange times in UTC and convert only for display. datetime.fromisoformat handles offsets (and Z since Python 3.11). Naive inputs are assumed to be UTC here, which is a decision you should make explicitly for your data.