Day 18: DST and The Related Software Bugs

This is one of two or three DST posts in the 30 Days of Time series. Today’s angle: the software bugs.

Twice a year, in most of the developed world, the clocks jump forward in spring and back in fall. The hour that doesn’t exist in spring materializes and then disappears in the fall. This is the source of more shipped bugs than any other single phenomenon in software.


The Two Impossible Hours

The mechanics, if you’ve never thought hard about them.

Spring forward. On the transition Sunday in March (in the US), the clock reads 01:59:59 and then immediately reads 03:00:00. The hour from 2:00 to 2:59 AM does not exist. 2:30 AM on that day is not a time. If you tell a computer to do something at 2:30 AM on that day, you have asked it to do something at a time that doesn’t exist.

What it does is up to the library:

  • It might silently skip.
  • It might silently run at 3:30 instead.
  • It might throw an exception.
  • It might run at the wrong time and silently throw your reports off.

The classic landmine is a daily task scheduled in local time, for example a job set to run at 1:30 AM. If you’re using the standard Linux cron daemon, it has battle-tested, built-in logic to detect DST transitions and prevent duplicates.

The problems are usually at the application layer. If you are using an application-level scheduler or Cron library that hasn’t been configured properly and blindly trusts the system clock, you can get into a situation where that 1:30 a.m. doesn’t exist or runs twice.


A Short Tour of Named Disasters

March 2007, United States. Congress passed the Energy Policy Act of 2005, which moved DST to begin three weeks earlier and end one week later. The change took effect in March 2007. Every system in the country running on a tz database older than mid-2006 spent three weeks in March, and one week in November, off by an hour. Banks ran payroll at the wrong time. BlackBerry calendars showed every meeting an hour off. Federal agencies had to issue advisories. The DOE later estimated the extension saved about 0.5% of electricity per day of extended DST, or roughly 1.3 TWh annually. The remediation cost across every affected piece of software in the country dwarfed that figure. (More on that later.)

New Year 2011, iOS. Non-recurring alarms set for January 1 or 2, 2011 did not fire, in any time zone. People slept through work. Apple’s official advice was to set one-time alarms as recurring until January 3. This was on top of an iOS DST bug from a few months earlier, when the fall 2010 transition shifted alarms by an hour in countries that had already changed clocks. Two months after the New Year’s bug, iOS again mis-handled the US spring DST transition. Apple released an apologetic fix and quietly rewrote the alarm subsystem.

Brazil, April 2019. Brazil canceled DST after decades of observing it, via Decree 9,764. This is fine for clocks going forward, but the cancellation was announced only a few months in advance, and the IANA tz database had to ship updates fast. Every Brazilian server running on a stale cache spent the next year an hour off, in particular for any future-scheduled event saved as “local time.”

Palestine. For about a decade running, Google Calendar shipped wrong DST data for Palestine, because the Palestinian Authority changes DST rules with short notice and the IANA volunteers don’t always learn in time. Meetings between Israeli and Palestinian colleagues would silently shift by an hour twice a year.


The Shape of the Failure

The DST bugs usually go like this:

  1. A piece of software was written with the assumption that local time is well-defined and monotonic.
  2. Local time is neither.
  3. The author never hit edge cases. It only happens twice a year, in certain regions, under certain settings.
  4. The bug ships. It runs fine for six months. Then it doesn’t.

The mitigations are well-known and this is why we do what we do.

  • Store UTC. Always. The IANA zone ID goes in a separate column. Never, ever store a naked local timestamp.
  • Recompute the local display every time. Treat local-time as a view, not data.
  • Never schedule anything between 2 and 3 AM local. That hour does not exist in your country half the time.
  • Use libraries that surface the ambiguity. The older Python pytz library would throw when you constructed an impossible local time. The modern zoneinfo handles it silently via a fold attribute, meaning you have to manually check for ambiguity. JavaScript’s Date produces inconsistent results across engines. The Temporal API, which reached Stage 4 in March 2026 and ships in Chrome 144, Firefox 139, and Node 26, lets you explicitly reject ambiguous times. Use it the soonest you can.
  • Keep tzdata current. This is a system-package problem and most teams forget about it until something breaks.

The tricky part of software has always been that we think that the wall clock or the wall time, the number you see on a daily basis is the same as the actual physical passage of time when in reality they are not. Daylight savings time is a really great example of the absurdity of our timekeeping.


Week 3 Recap

If this is the first time you are reading this series I figured a recap is order. Week 3 has been about the infrastructure of practical timekeeping, the layer where computers, calendars, and humans actually have to agree on what time it is.

The picture I want to leave you with is that every problem we’ve covered in Week 3 is a downstream consequence of a deeper one. The system isn’t fragile because of bad programmers. It’s fragile because the underlying thing, “what time is it, here, right now,” was never a single answer, and we’ve been pretending it was.


What’s Coming

Week 4 is about the cracks. What if a minute had 61 seconds? What if October had only 21 days? What if every meeting on every calendar landed on the same weekday, forever? Each of those has actually happened, or is being voted on, or was almost adopted. Week 4 covers leap seconds and their abolition, the DST fight nobody can win, and the calendars we use, almost used, and may yet use.


Sources

I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].

/ Programming / Time / 30daysoftime / Dst / Software bugs