Exercise 3 solution from datetime import datetime, timezone from zoneinfo import ZoneInfo def classify(dt): first = dt.replace(fold=0).utcoffset() second = dt.replace(fold=1).utcoffset() if first == second: return "normal" return "repeated" if first > second else "gap" ny = ZoneInfo("America/New_York") lon = ZoneInfo("Europe/London") tests = [ ("New York", datetime(2026, 3, 8, 2, 30, tzinfo=ny)), ("New York", datetime(2026, 11, 1, 1, 30, tzinfo=ny)), ("New York", datetime(2026, 11, 1, 2, 30, tzinfo=ny)), ("London", datetime(2026, 3, 29, 1, 30, tzinfo=lon)), ("London", datetime(2026, 10, 25, 1, 30, tzinfo=lon)), ("London", datetime(2026, 7, 4, 12, 0, tzinfo=lon)), ] for city, dt in tests: print(f"{city:<9} {dt:%Y-%m-%d %H:%M} {classify(dt)}") rep = datetime(2026, 11, 1, 1, 30, tzinfo=ny) for f in (0, 1): r = rep.replace(fold=f) print(f"fold={f}: {r.tzname()} UTC {r.astimezone(timezone.utc):%H:%M}") Output (run, and exactly as shown): New York 2026-03-08 02:30 gap New York 2026-11-01 01:30 repeated New York 2026-11-01 02:30 normal London 2026-03-29 01:30 gap London 2026-10-25 01:30 repeated London 2026-07-04 12:00 normal fold=0: EDT UTC 05:30 fold=1: EST UTC 06:30 Explanation: the same wall reading is asked for its offset with fold=0 and fold=1. If the two answers agree the time is ordinary. In a repeated hour the first pass has the larger offset (summer time), so first > second. In a gap Python's convention gives the pre-jump offset for fold=0 and the post-jump offset for fold=1, so first < second. New York 02:30 on 1 November is ordinary because the repeated hour there is 01:00-02:00. The final lines show the two passes through the repeated hour are one real hour apart in UTC.