Exercise 1 solution from datetime import datetime, timezone def describe(text): d = datetime.fromisoformat(text) if d.utcoffset() is None: return text + " naive" utc = d.astimezone(timezone.utc) return f"{text} aware offset {d.utcoffset().total_seconds() / 3600} hours utc {utc.isoformat()}" for s in ["2026-03-05T09:00:00", "2026-03-05T09:00:00Z", "2026-03-05T14:30:00+05:30", "2026-03-05T23:00:00-04:00"]: print(describe(s)) Output (run, and exactly as shown): 2026-03-05T09:00:00 naive 2026-03-05T09:00:00Z aware offset 0.0 hours utc 2026-03-05T09:00:00+00:00 2026-03-05T14:30:00+05:30 aware offset 5.5 hours utc 2026-03-05T09:00:00+00:00 2026-03-05T23:00:00-04:00 aware offset -4.0 hours utc 2026-03-06T03:00:00+00:00 Explanation: the test for "naive" is utcoffset() returning None; checking tzinfo alone is not quite enough. The "Z" ending is accepted from Python 3.11 and means an offset of zero. The first and third inputs are different text but the same instant only if both are aware; the naive one carries no offset, so it gets no UTC conversion (astimezone on a naive value would guess the machine's own zone, which is why the function avoids it). The last line shows that converting can change the calendar date: 23:00 at -4 hours is already the next day in UTC.