Python Datetime and Timezone Handling Prompt
Handle dates, times, timezones, and durations correctly in automation scripts — UTC-everywhere storage, aware datetimes, DST-safe scheduling, and reliable parsing/formatting of timestamps.
- Target user
- Automation engineers fighting off-by-an-hour bugs and naive-datetime crashes
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior Python engineer who has audited the off-by-one-hour and "works until DST" bugs that plague time handling in automation.
I will provide:
- The script or function that touches dates/times
- Where timestamps come from (logs, APIs, user input, the system clock) and where they go (DB, files, other APIs)
- The Python version (so we know if `zoneinfo` is available — 3.9+)
Your job:
1. **Find the naive datetimes** — flag every `datetime.now()`, `datetime.utcnow()` (deprecated and dangerous), `fromtimestamp` without tz, and any arithmetic mixing aware and naive objects.
2. **Establish the discipline** — store and compute in UTC with timezone-aware objects (`datetime.now(timezone.utc)`), convert to local/display tz only at the edges. Make this rule explicit in a one-line comment at each boundary.
3. **Parse robustly** — use `datetime.fromisoformat` for ISO-8601, `zoneinfo.ZoneInfo("Region/City")` for named zones, and explain why parsing with `strptime` + `%Z` is unreliable. Handle the missing-timezone case explicitly rather than assuming local.
4. **Do DST-safe math** — show that adding `timedelta(days=1)` to wall-clock time is not the same as adding 24 hours across a DST boundary, and demonstrate the correct approach for "same time tomorrow" scheduling.
5. **Format for the audience** — UTC ISO-8601 with offset for logs and machines, human-readable local time for humans, and never log ambiguous local times without an offset.
6. **Cover monotonic needs** — recommend `time.monotonic()` for measuring elapsed time and timeouts, since wall-clock can jump backward via NTP.
7. **Test the edge cases** — leap seconds aside, write `pytest` cases for the DST fall-back ambiguous hour, the spring-forward gap, and a non-UTC input source.
Output as: (a) annotated before/after of the risky code, (b) a small `tz` helper module, (c) the pytest cases for DST boundaries.
Bias toward: aware-UTC everywhere, explicit conversion at boundaries, and never trusting the system local timezone implicitly.