Daylight Saving Time Edge Cases

May 28, 20267 min read

Why DST Breaks Software

Daylight Saving Time is a political decision, not a physical one. Governments decide when — or whether — to shift clocks. Rules change, exceptions appear, and some regions abolish DST entirely after decades of observance.

Your code needs to handle three categories of DST problems: timestamps that exist twice, timestamps that never exist, and durations that are not what you expect.

The Ambiguous Hour

When clocks fall back, one local time occurs twice.

2025-11-02 01:30:00 EDT (UTC-4)
2025-11-02 01:30:00 EST (UTC-5)

Both timestamps look identical in local time: 01:30. Without an offset or timezone identifier, you cannot tell which one a user means.

How it breaks code

// DANGEROUS: parsing without timezone context
const local = new Date('2025-11-02 01:30:00')
// Browser assumes the SECOND occurrence (EST) — but your user might mean the first (EDT)

How to handle it

Always store and compute in UTC. Convert to local time only for display. When a user enters 01:30 on a fall-back date, ask which occurrence they mean, or disambiguate using the IANA timezone database.

// Using Intl to check ambiguity
const tz = 'America/New_York'
const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: tz,
  year: 'numeric', month: '2-digit', day: '2-digit',
  hour: '2-digit', minute: '2-digit', timeZoneName: 'short'
})

// Same wall time, two UTC equivalents
const edt = new Date('2025-11-02T05:30:00Z') // 01:30 EDT
const est = new Date('2025-11-02T06:30:00Z') // 01:30 EST

formatter.format(edt) // "11/02/2025, 1:30 AM EDT"
formatter.format(est) // "11/02/2025, 1:30 AM EST"

The Missing Hour

When clocks spring forward, one local time never exists.

2025-03-09 02:30:00 — this time does not exist in America/New_York

Clocks jump from 01:59:59 EST directly to 03:00:00 EDT. Any timestamp between 02:00 and 03:00 on that date is phantom.

How it breaks code

// User schedules a recurring event at 2:30 AM daily
// On March 9, that time does not exist
// Different systems handle this differently:
// - Some move it to 3:30 AM (spring forward)
// - Some move it to 1:30 AM (fall back)
// - Some silently drop the event

How to handle it

Validate user-input times against the IANA database. If a time falls in a gap, present a clear message: "This time does not exist on this date due to Daylight Saving Time. Please choose 1:30 AM or 3:30 AM."

Duration Shifts

A "24-hour" period does not always contain 24 hours in local time.

Spring forward: 23-hour day

March 9, 2025: 1:00 AM EST → March 10, 2025: 1:00 AM EDT = 23 hours

Fall back: 25-hour day

November 2, 2025: 1:00 AM EDT → November 3, 2025: 1:00 AM EST = 25 hours

How it breaks code

// WRONG: assuming 24 hours per day
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000)
// On a spring-forward day, this lands on the SAME calendar date at 1:00 AM EDT
// instead of the next day's midnight

// CORRECT: use date arithmetic, not millisecond arithmetic
const tomorrow = new Date(today)
tomorrow.setDate(tomorrow.getDate() + 1)

For scheduling: always compute durations in UTC. Display in local time. A daily recurring event should be stored as "daily at 14:00 UTC" rather than "daily at 9:00 AM Eastern" — the latter shifts with DST.

International Edge Cases

The Southern Hemisphere

Countries below the equator observe DST in opposite months. Australia springs forward in October and falls back in April. If your team is in New York and your users are in Sydney, both hemispheres' transitions affect your application.

Regions that abolished DST

The European Union voted to abolish DST in 2019. Implementation has been delayed repeatedly. Your code should rely on the IANA database, not assumptions about which countries observe DST.

Notable non-observers:

  • Japan (never observed)
  • China (single timezone, no DST)
  • India (no DST)
  • Arizona (most of the state; the Navajo Nation does observe DST)
  • Hawaii (no DST)

Last-minute rule changes

Brazil abolished DST in 2019, then reinstated it temporarily in 2021 during a power crisis. Russia moved between permanent summer time, permanent winter time, and back. Your timezone library must be updated regularly to track these changes.

Timezone Selection Anti-Patterns

Anti-patternWhy it failsCorrect approach
Hardcoding UTC offsetsOffsets change with DSTUse IANA identifiers
Using abbreviations (EST, CST)Ambiguous across regionsUse America/New_York, America/Chicago
Storing local time without timezoneCannot reconstruct UTCStore UTC + IANA timezone
Assuming DST dates are fixedGovernments change rulesKeep IANA database updated
Testing only summer datesMisses fall-back ambiguitiesTest both transition dates

Key Takeaways

  • DST creates ambiguous hours (fall back) and missing hours (spring forward) — always validate user input against the IANA database
  • Store timestamps in UTC; convert to local time only for display
  • Never assume days are 24 hours — use date arithmetic, not millisecond arithmetic
  • Southern Hemisphere DST operates in opposite months — global apps must handle both
  • Regions change DST rules without warning — keep your timezone library updated
  • Always use IANA timezone identifiers, never abbreviations or hardcoded offsets

Try It Yourself

Convert times across DST boundaries safely with our free Timezone Converter. All conversions use IANA timezone data with automatic DST adjustment — no manual offset lookup needed.