Saved

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:

  1. Store times as UTC instants (Unix timestamp or ISO 8601 with explicit offset)
  2. Record the IANA zone ID separately for display purposes (e.g. America/New_York, not -05:00)
  3. Use a timezone-aware datetime library — do not manually apply offsets
  4. 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.DateTimeFormat in JavaScript and always pass a timezone ID, not an offset
  • In Python, use zoneinfo (Python 3.9+) or pytz, not naive datetime objects
  • In databases, store TIMESTAMPTZ (PostgreSQL) or equivalent UTC type — never TIMESTAMP WITHOUT TIME ZONE for 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.