Utilix knowledge base
Daylight Saving Time Edge Cases
Published May 1, 2026
Daylight Saving Time (DST) is responsible for a disproportionate number of bugs in calendar, scheduling, and logging systems. The root issue is that local time is not a continuous, monotonic sequence — it skips forward and doubles back.
The two problem moments
Spring forward (gap)
When clocks advance — typically by one hour at 2:00 AM — the local time jumps from 2:00 AM directly to 3:00 AM. The hour from 2:00 to 3:00 does not exist in local time that day.
Consequences:
- A scheduled job set to run at 2:30 AM never fires on that date
- Displaying "2:30 AM on March 9" for a US Eastern date returns an invalid local time
- Duration calculations that cross this gap will be off by one hour
Fall back (ambiguity)
When clocks retreat — typically from 2:00 AM back to 1:00 AM — the hour from 1:00 to 2:00 happens twice. There are two distinct instants in time, both labelled "1:45 AM".
Consequences:
- A log entry showing "1:45 AM" is ambiguous — is it the first or second occurrence?
- A meeting scheduled at "1:30 AM local" on a fall-back night has an undefined absolute time
- Billing systems that charge per clock-hour may count this hour twice or not at all
Countries that do not observe DST
Not all regions change clocks:
- No DST: China, India, Japan, most of Africa, large parts of South America, Iceland, Arizona (US), Saskatchewan (Canada)
- Southern Hemisphere: DST runs during their summer (October–March), opposite to the Northern Hemisphere
This means "9:00 AM London / 5:00 PM Sydney" is valid for part of the year and off by an hour for another part — even when both cities observe DST — because their transitions happen at different calendar dates.
The right way to store and display times
Wrong:
meeting_time = "2026-11-01 01:30:00" // what timezone? which 1:30?
Right:
meeting_time = "2026-11-01T01:30:00-04:00" // UTC-4 = first occurrence
meeting_instant_utc = 1762050600 // Unix timestamp, unambiguous
timezone = "America/New_York" // IANA zone ID for rendering
Rules:
- Store times as UTC instants (Unix timestamp or ISO 8601 with explicit offset)
- Record the IANA zone ID separately for display purposes (e.g.
America/New_York, not-05:00) - Use a timezone-aware datetime library — do not manually apply offsets
- For recurring events (weekly meeting), store the wall-clock rule (every Tuesday at 9 AM New York) and re-resolve the next absolute instant, so it stays "9 AM after DST transitions
Code-level mitigations
- Use
Intl.DateTimeFormatin JavaScript and always pass a timezone ID, not an offset - In Python, use
zoneinfo(Python 3.9+) orpytz, not naivedatetimeobjects - In databases, store
TIMESTAMPTZ(PostgreSQL) or equivalent UTC type — neverTIMESTAMP WITHOUT TIME ZONEfor user-facing events - For scheduled jobs, prefer cron with timezone-aware scheduling (
cron(0 9 * * ? TZ=America/New_York)in AWS)
Our Timezone Converter reflects IANA rules for historical and future transitions where data is available.