October 12, 2026 · 3 min read · Yunus Emre Vurgun
Timestamps, Time Zones, and Half-Open Intervals
An instant, a calendar date, and a recurring local appointment are different kinds of information. Encoding all three as one vaguely named date field creates subtle bugs when users travel, clocks change, or a report crosses a day boundary.
Use an offset-bearing timestamp for an instant. Use a civil date for a birthday or accounting date when no time of day is intended. For a recurring local appointment, preserve the local rule and a named time zone. A numeric offset identifies an offset at a moment; it does not encode a region’s future time-zone rules.
Declare the representation at the boundary
{
"occurred_at": "2026-10-12T09:00:00Z",
"report_date": "2026-10-12",
"appointment_local_time": "09:00",
"appointment_zone": "Europe/Istanbul"
}These fields describe different concepts deliberately. If an API uses epoch values, make the unit explicit, for example occurred_at_ms. A seconds-versus-milliseconds mistake can move a date decades away while still producing a parseable number. Validate plausible ranges as well as structural types.
Do not turn a birthday into midnight UTC just to fit a timestamp column. A client displaying it in another zone can show the previous date. Likewise, converting a recurring local appointment once to UTC can lose the intended local-hour rule when time-zone policies change.
Use adjacent windows that share no event
WHERE occurred_at >= :start
AND occurred_at < :endA half-open interval includes the start and excludes the end. Two neighboring windows can meet at one boundary without both counting the event there. Compute the start and end in the intended reporting zone, then compare instants consistently. A local day is not always the same duration in every region.
Test events just before, exactly at, and just after the boundary. Include fractional-second precision and the database’s actual storage resolution. Avoid converting every timestamp to a formatted string before comparison; that can obscure both correctness and index use.
Measure elapsed time with the right clock
Use a monotonic clock for a timeout or performance duration where the runtime provides one. A wall clock is for human time and can be adjusted. Record absolute timestamps for correlation, but calculate elapsed work from a suitable duration source.
Keep runtime and time-zone data current, and document how ambiguous or nonexistent local times are resolved. A useful timestamp contract states the unit, offset policy, precision, and semantic meaning, not merely that the field contains an ISO-style string.
Reference tables to keep nearby
- Date and Time Interchange Patterns — Representing instants, civil dates, time zones, recurring schedules, and intervals without hidden assumptions.
Primary sources
These are the specifications and project documentation behind the examples. Check the relevant implementation and version before applying a pattern.