from __future__ import annotations from datetime import datetime, timezone def to_naive_utc(dt: datetime | None) -> datetime | None: """ Convert a timezone-aware datetime to naive UTC (tzinfo removed). Our DB columns are DateTime without timezone. Persisting timezone-aware datetimes can cause runtime errors (especially on Postgres). """ if dt is None: return None if dt.tzinfo is None: return dt return dt.astimezone(timezone.utc).replace(tzinfo=None) def to_iso_utc(dt: datetime | None) -> str | None: """ Serialize a datetime as an ISO-8601 UTC string. - If dt is timezone-aware: convert to UTC and use "Z". - If dt is naive: treat it as UTC and use "Z". """ if dt is None: return None if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) else: dt = dt.astimezone(timezone.utc) return dt.isoformat().replace("+00:00", "Z")