Home / Blog / Time Zones Will Break Your App: A Field Guide for Developers
EngineeringOctober 26, 2026·3 min read

Time Zones Will Break Your App: A Field Guide for Developers

Practical rules for storing, converting, and displaying timestamps so your app survives time zones, DST, and future-dated events.

Every team hits it eventually: a report that's off by one day, a reminder that fires at 3 a.m., a "daily" job that runs twice. Time zone bugs are rarely dramatic — they're quiet, intermittent, and discovered by annoyed users. The good news: a handful of rules prevents almost all of them.

Rule 1: Store moments in UTC

A moment is something that happened or will happen at a specific instant — an order placed, a payment captured, a message sent. Store these as UTC timestamps (TIMESTAMPTZ in Postgres, epoch milliseconds, or ISO 8601 with offset). Convert to local time only at the edge, when rendering for a human.

Why at the edge? Because the same moment is "Tuesday evening" in Jakarta and "Tuesday morning" in New York. If you bake a local time into storage, you've frozen one interpretation and lost the ability to serve the others.

Rule 2: Civil time is not a moment

Here's where "always use UTC" breaks down. A doctor's appointment at "9:00 a.m. on March 14" or a store that opens "daily at 8:00" is civil time — a wall-clock agreement, not an instant. If you convert it to UTC at write time and the region's offset rules change (governments adjust DST and zones more often than you'd think), your stored instant is now wrong.

For future events tied to a wall clock, store the local date-time plus the IANA zone name (Asia/Jakarta, not +07:00), and resolve to an instant as late as possible.

Offsets describe a moment; zone names describe the rules for a place. +07:00 can't tell you what 8 a.m. means next year. Asia/Jakarta can.

Rule 3: "A day" depends on who's asking

Daily revenue reports are a classic trap. "Sales for October 26" means midnight-to-midnight in the merchant's zone — but if your query groups by the UTC date, every transaction after 5 p.m. Jakarta time lands on tomorrow's report. The numbers look plausible and reconcile to nothing.

Rule 4: Test the ugly cases

Time zone code looks correct for eleven months a year. Make your tests cover the other cases on purpose:

The takeaway

Two kinds of time, two strategies: instants in UTC, civil times with an IANA zone name. Convert at the edges, define the business day explicitly, and test the boundaries. None of this requires a library beyond what your language ships — just the discipline to decide, once, what every timestamp in your system actually means.

Build with Abati Technology

We build software that ships — WhatsApp API, developer tools, POS, and mobile apps. Let's talk about your project.

Get in Touch →