Time looks like a solved problem right up until a system has users in more than one place. A row says an event happened at 14:30. Fourteen-thirty where? On whose clock? If the answer is “the server’s,” then the answer changes when the server moves, and every historical row silently means something slightly different than it did. A timestamp without an unambiguous reference point isn’t data — it’s a note whose meaning depended on context that wasn’t written down, which is the same failure this blog described about column semantics, in a domain where the ambiguity is easier to miss because everyone assumes they already understand time.

The reliable division is between an instant and a civil time, and they aren’t interchangeable. An instant is a specific moment in the history of the universe: when the payment cleared, when the row was written, when the request arrived. It should be stored as an unambiguous absolute, converted to a local representation only when displayed. A civil time is a human intention that isn’t fixed to an instant until you know a place: “the report runs at 9 a.m.” means 9 a.m. wherever the person lives, and if you resolve that to an instant at the moment they configure it, you get a schedule that silently shifts by an hour twice a year. Storing the wrong one of these two things is the root of a large fraction of time bugs.

Daylight-saving transitions are where the difference becomes visible, and they misbehave in both directions. In spring some local times don’t exist at all, so a job scheduled at 2:30 a.m. has no instant to run at. In autumn some local times happen twice, so the same job can fire twice — which, if it isn’t idempotent, is the retries problem arriving through a different door. Neither case is exotic; both arrive on a known schedule, twice a year, and both are entirely invisible in testing unless someone deliberately runs the clock across the boundary.

Then there’s the boundary that isn’t a moment at all: “today.” A daily report, a usage quota, a billing period — each requires deciding whose day it is. The user’s, the account’s, the company’s, UTC’s? Every one of those is defensible and they produce different numbers, which is how two dashboards end up disagreeing about yesterday’s total and both being right. The decision is unavoidable; the mistake is making it implicitly, in whichever function happened to be convenient, and then discovering the inconsistency during a customer’s month-end reconciliation.

None of this requires exotic machinery. Store instants as absolutes. Store civil times with the zone they were intended in, and resolve them at execution rather than at configuration. Write down which day boundary a periodic thing uses. It’s cheap in advance and unpleasant to retrofit, because by then the ambiguity is baked into years of stored rows — the same asymmetry that shows up everywhere in this blog, arriving here in a domain everyone believes they already understand.