Prompt
How do I handle time zones and daylight saving time in scheduling?
Latest observation
The safest rule is:
Store and compare times in UTC, but schedule and display in the user’s intended local time zone.
Here’s the practical approach.
1) Store the original time zone, not just the offset
Don’t store only -05:00 or +02:00. Offsets change with daylight saving time.
Store:
- the event’s local date/time
- the IANA time zone name, like:
America/New_YorkEurope/LondonAsia/Tokyo
Example:
- Meeting:
2026-03-10 09:00 - Time zone:
America/New_York
That lets you correctly interpret future DST changes.
2) Convert to UTC for persistence and computation
When the user picks a local scheduled time:
- interpret it in the chosen IANA time zone
- convert it to UTC
- store that UTC timestamp for execution/comparison
This prevents ambiguity when comparing across regions.
3) Be careful with recurring schedules
Recurring schedules are where DST problems usually happen.
Ask: should the job run at:
- the same wall-clock time locally, e.g. every day at 9:00 AM New York time
- or the same absolute instant, e.g. every 24 hours
These are different.
For “every day at 9:00 AM local time”:
- recalculate the next occurrence in the local time zone each time
- don’t just add 24 hours
Otherwise, DST shifts will move the job to 8 AM or 10 AM.
4) Handle ambiguous and missing local times
DST creates tricky times:
Spring forward
Some local times do not exist.
Example: 2026-03-08 02:30 in many US zones may be skipped.
Fall back
Some local times happen twice.
Example: 2026-11-01 01:30 may occur twice.
Your system should define a policy:
- reject invalid times and ask the user to choose another time
- or automatically resolve them consistently:
- for nonexistent times: move forward to the next valid time
- for ambiguous times: choose earlier or later occurrence explicitly
5) Use a real time zone library
Use libraries that understand IANA zones and DST rules.
Examples:
- JavaScript:
Luxon,date-fns-tz,Temporalpolyfill - Python:
zoneinfo(preferred),pytzlegacy - Java:
java.time - .NET:
TimeZoneInfo - Go:
timepackage with location support - Ruby:
TZInfo
Avoid hand-rolled offset math.
6) Always display times in the user’s local zone
When showing scheduled events:
- convert from stored UTC to the relevant IANA zone
- display the zone or offset if confusion matters
Example:
- “9:00 AM America/New_York”
- or “9:00 AM EDT”
7) Log and audit in UTC
For debugging and traceability:
- log timestamps in UTC
- optionally include the source time zone for context
8) If scheduling across users, be explicit
If one user creates an event for another user:
- specify whose time zone controls the schedule
- don’t assume the creator’s zone
Simple rule of thumb
- User input: local time + IANA zone
- Storage: UTC timestamp + IANA zone
- Display: convert UTC back to local zone
- Recurring: recalculate in local zone, not by adding fixed hours
If you want, I can also show:
- a database schema for this,
- code examples in Python/JavaScript/Java,
- or a DST-safe recurrence algorithm.