5 Checks to Kill Timezone Bugs
Why Timezone Bugs Only Surface Late
Date and time bugs rarely reproduce in dev. Your test runs happen mid-afternoon in your own timezone, missing every DST boundary, month-end, and leap day. The result: a bug that only appears in production, on one specific date. That's not bad luck — it's a missing checklist. Timezone bugs are cheapest to catch structurally, during implementation, not after a report arrives.
5 Patterns to Check While Implementing
1. Missing UTC conversion
Storing a user's input as the server's local time, then showing it to a user elsewhere, shifts the displayed hour. Rule: always store UTC, convert to the user's timezone only at display time.
# Wrong: stores local time
Time.now
# Right: store UTC, convert on display
Time.now.utc
user_time_zone.at(record.created_at)2. DST boundaries
DST regions have one hour that doesn't exist, or repeats, twice a year. Computing "24 hours later" as raw seconds drifts by an hour across a DST changeover. Let a timezone-aware library do the addition, not raw seconds.
3. Month-end dates
Adding "one month" to January 31 hits a February with no 31st. Whether your library rolls to March 3 or clamps to February's last day must be checked before implementation and written into the spec — this bites subscription and billing dates often.
4. Leap years
Date-range math, age calculations, and renewal logic spanning February 29 break in leap years. Don't hand-roll leap-year detection — delegate it to your standard library.
5. Locale-dependent format strings
"03/04/2026" reads as March 4 in the US, April 3 in Japan. Anywhere dates travel as strings, standardize on ISO 8601 (YYYY-MM-DD) and format for locale only at display time. Never let a locale-dependent format leak into an API response or a log line.
Concrete Dates Worth Testing
- Leap year: 2028-02-29
- DST start (spring, US): 2027-03-14
- DST end (fall, US): 2026-11-01
- Month-end + 1 month: add one month to 2026-01-31, check you land on 2026-02-28
- Timezone date-boundary skew: UTC+14 (Kiribati) vs. UTC-12 can put the same instant on two different calendar dates
Bake these dates into fixed test data or E2E scenarios, and you catch them at implementation time instead of in production.
Putting This Into Practice With Bugoon
Timezone bugs are expensive to reproduce once a report lands, because a vague "when" leaves the developer guessing which timezone or instant is meant. Bugoon's widget captures a screenshot and operation steps at report time and files them into a GitHub Issue, so reproduction context isn't lost. That Issue is reachable from Claude Code or Cursor through the MCP server, so you can apply the checklist above right where the report landed.
Recording the report's send time with its timezone could make it easier to tell whether a bug is timezone-related in the first place — though that's an idea being explored, not something currently implemented.
Streamline bug reporting for your team.
Bugoon is free to get started. Add one line of code to your site and transform how your team handles bugs.
Get Started