Time Zones and Date Math: Avoiding the Off-by-One-Day Bug
Why a date that looks right in one time zone is wrong in another, and the simple rule that fixes most date-math bugs in software.
You ask the server for "events on 2026-07-04". You get nothing. You're sure you just added one.
It's almost always a time-zone mismatch. The row is stored as a UTC instant, and the user's day starts and ends at a different moment than the database's day.
Civil dates vs instants
A civil date is a calendar concept: "the Fourth of July, 2026." An instant is a single point in time. Same instant, different civil date in different zones. 23:30 on July 4 in New York is already July 5 in London.
The rule
- Store and transmit instants in UTC. ISO 8601 with a Z, or a Unix epoch.
- Convert to the user's local civil date only when you display it.
- For "all events on day X" queries, take the user-local start and end of day, then convert those to UTC for the query.
Daylight saving
DST adds two more landmines. A 23-hour day in spring (an hour disappears) and a 25-hour day in fall (an hour repeats). Never compute "tomorrow" by adding 24 hours. Add one calendar day in the target zone instead. Our Time Duration Calculator handles both cases.