Every developer eventually writes 24 * 60 * 60 to mean "one day". Every developer is eventually wrong. DST makes one day a year 23 hours long, another 25. Time zones shift. Countries change their rules. Here are the traps that bite.
The 23-hour day and the 25-hour day
Most of the US, Canada, Europe, and Australia observe Daylight Saving Time. Twice a year, clocks jump — one day becomes 23 hours long ("spring forward"), the other 25 hours ("fall back"). Any piece of code that assumes "one day = 86,400 seconds" breaks on those two days every year.
Examples of things that go wrong:
- Countdowns — a countdown to "tomorrow at 9 AM" actually lands at 10 AM (spring forward) or 8 AM (fall back) if you compute it naively.
- Billing cycles — a monthly charge at midnight runs twice during fall-back or gets skipped during spring-forward, depending on how it's coded.
- Calendar events — a recurring meeting at 9 AM Eastern drifts by an hour if the calendar stores UTC and the user’s timezone changes.
The "ambiguous midnight" problem
During fall-back, 1:00 AM happens twice. At 2:00 AM the clock jumps back to 1:00 AM. So "1:30 AM on Nov 3" is ambiguous — there are two different absolute moments that match that wall-clock time. Any code that uses local time for events in that hour needs to pick one or raise an error.
Conversely, during spring-forward, 2:30 AM doesn't exist. The clock goes from 1:59 AM straight to 3:00 AM. Events scheduled in the missing hour silently shift — or, worse, fail in ways that aren't obvious.
UTC as the escape hatch
UTC doesn't observe DST. It doesn't jump. It's a clean monotonic clock maintained by atomic timestamps plus leap-second adjustments. Store everything in UTC. Convert to local time only for display. The pattern is simple and it solves 95% of timezone bugs.
The other 5%
Two cases UTC doesn't solve cleanly:
- Wall-clock events. An alarm at 9 AM means "when my wall clock reads 9", not "14:00 UTC". If the user changes timezone, the alarm should still fire at 9 AM local. This requires storing the timezone identifier along with the time, not just UTC.
- Future timezone changes. Countries occasionally change their DST rules with a few months' notice. An event scheduled 5 years out may land on a different UTC offset than expected. The IANA time zone database tracks these changes; keep it updated.
The 2038 problem
32-bit signed epoch seconds overflow at 03:14:07 UTC on 2038-01-19. Any system using 32-bit Unix time breaks on that day. Most modern systems use 64-bit time — enough to last until the year 292,277,026,596 — but legacy embedded systems, old databases, and some C code still use 32-bit. Like Y2K, it'll be a slow grind of finding and fixing the affected systems before the deadline.
Tool uses local time interpretation with awareness of DST. For fixed-absolute countdowns, use ISO format.

