Keep an instant in UTC while displaying local time

Keep a single canonical instant in UTC when an event can be viewed in more than one location. In this example, the stored value is 15:45 UTC on 15 January 2025. A viewer in Tokyo receives a derived display value of 00:45 on the following calendar day, with a +09:00 offset. The UTC value remains unchanged; astimezone() returns another representation of the same instant.

This separation helps avoid treating a display clock reading as the event's stored identity. The first assertion verifies the exact Tokyo representation for this fixed example. The second uses timestamp() to compare instants, rather than comparing local hour fields that are expected to differ. In a real data model, serialize or persist the aware UTC value and perform the zone conversion near the presentation boundary.

Use an IANA identifier such as Asia/Tokyo through ZoneInfo, not a hand-written numeric offset for zones whose rules can change. ZoneInfo is available starting with Python 3.9. It relies on installed time-zone data and can fail to find a zone when that data is unavailable. Also, a conversion cannot resolve an originally ambiguous or nonexistent local wall time; establish the correct instant before storing it. The relevant behavior is documented in Python's zoneinfo module and datetime.timestamp().

AI assistance disclosure: this article was drafted with AI assistance and should be reviewed for the application's time-handling policy.

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

stored_instant = datetime(2025, 1, 15, 15, 45, tzinfo=timezone.utc)
tokyo_display = stored_instant.astimezone(ZoneInfo("Asia/Tokyo"))

assert tokyo_display.isoformat() == "2025-01-16T00:45:00+09:00"
assert tokyo_display.timestamp() == stored_instant.timestamp()

print(f"stored: {stored_instant.isoformat()}")
print(f"display: {tokyo_display.isoformat()}")
stored: 2025-01-15T15:45:00+00:00
display: 2025-01-16T00:45:00+09:00

Comments

Popular posts from this blog

Compare Two Text Files in Python Without Modifying Them

Seven CSV Quality Checks to Run Before Importing Data

Explain why SQLite transactions cannot make an HTTP call atomic