Batu Lab NotesPractical developer guides

Compare aware datetimes only after choosing time zones

By Batu · English technical notes

Also published in our Blogger archive.

An aware datetime includes a UTC offset, so it can identify an instant. For a comparison that is easy to inspect and log, first choose UTC as the common zone and call astimezone(timezone.utc) on both values. The example starts with 09:00 at UTC−04:00 and 14:30 UTC. Conversion makes their actual instants explicit: 13:00 UTC and 14:30 UTC, so the first is earlier.

The assertions check this particular conversion and ordering; they do not validate that an external timestamp was labelled with the correct time zone. Attaching a tzinfo to a naive wall-clock value is an interpretation decision, not a conversion. Determine that zone from the data contract before constructing the aware value. Do not mix naive and aware datetimes in ordering logic: a naive value has no unambiguous position on the UTC timeline.

This uses datetime, timedelta, timezone, datetime.astimezone(), and datetime.isoformat() from the standard library. Fixed-offset timezone is sufficient for the synthetic example, but it does not model historical offset or daylight-saving rules; use a rule-based zone where the business meaning requires one. astimezone() is available in supported modern Python versions; this example works on Python 3.6+.

Read the Python datetime documentation for aware objects, UTC offsets, and conversion behavior.

AI-assistance disclosure: This article was drafted with AI assistance and should be reviewed in its application context.

from datetime import datetime, timedelta, timezone

left = datetime(2026, 5, 1, 9, 0, tzinfo=timezone(timedelta(hours=-4)))
right = datetime(2026, 5, 1, 14, 30, tzinfo=timezone.utc)

left_utc = left.astimezone(timezone.utc)
right_utc = right.astimezone(timezone.utc)

assert left_utc < right_utc
assert left_utc.isoformat() == "2026-05-01T13:00:00+00:00"

print(left_utc.isoformat())
print(right_utc.isoformat())
print(left_utc < right_utc)
2026-05-01T13:00:00+00:00
2026-05-01T14:30:00+00:00
True