By Ether DataRequest data sample
All sections

Time Uncertainty

An instant is a point estimate plus an error bar; near an hour boundary the ±window straddles two slots, so the assignment is not unique — the temporal weighted crosswalk.

stable2 min read
Source time
instant, clock_metadata
Destination time
uncertain_instant, slot_set
weighted

The geo KB's core discipline is that a lat/long is a location plus an error bar, and a point is assigned to cells at the resolution matched to that error, never snapped. Time has the exact same structure: a timestamp is an instant plus a ± window, and a slot assignment is only safe when the whole window falls inside one hour-of-week slot.

Instead of storing

2026-07-12T14:31:02Z

store

2026-07-12T14:31:02Z ±200ms

This is routine in astronomy, robotics, sensor fusion, autonomous vehicles, and increasingly in AI pipelines, where a fix carries a stated accuracy.

The straddle

The canonical slot is a whole UTC hour. When the ± window crosses an hour boundary the instant has more than one candidate slot — the direct temporal analog of a geo cell straddling a boundary. Snapping to the point estimate throws away the fact that the true slot is uncertain.

Certain only when the window fits

A ±20 ns GPS fix is certain: one slot. A ±200 ms phone fix at 14:59:59.900 is not: it straddles 15:00 and belongs partly to two slots. Report both candidates and a confidence — do not pretend to a single answer the clock could not give.

The model, made checkable

import {
  fromClock,
  candidateSlots,
  slotIsCertain,
  slotConfidence,
} from "@/lib/time";

// A ±200 ms fix at 00:59:59.900 UTC straddles the 00:00 → 01:00 boundary.
const u = { epochMs: Date.UTC(2026, 6, 27, 0, 59, 59, 900), plusMinusMs: 200 };
slotIsCertain(u); // false
candidateSlots(u); // [0, 1] — both hour-of-week slots the window touches
slotConfidence(u); // ~0.5 — fraction of the window in the point-estimate slot

// Build the uncertainty straight from a clock's stated accuracy:
const g = fromClock(Date.UTC(2026, 6, 27, 0, 30), { source: "gps", accuracyMs: 0.00002, model: "utc" });
slotIsCertain(g); // true — one slot

The tested reference implementation is lib/time/uncertainty.ts. In Python the same idea is a (datetime, timedelta) pair; enumerate the slots at t - Δ and t + Δ and every hour boundary between.

Relationship to grain and false precision

Uncertainty and resolution/grain are two sides of one coin: never claim a slot finer than the clock supports. A nanosecond timestamp from a clock accurate to ±1 second is false precision — the extra digits are noise that can flip a near-boundary assignment. Carry the accuracy so downstream code weights, rather than trusts, the point estimate.

For values that are intervals rather than points — a one-minute average, a scrape window — the same machinery applies: assign to slots by overlap, weighted, not to a single slot.

Edge cases affecting this page

Temporal ProvenanceProvenance & uncertaintyThe 168 AxisConceptual modelResolution and GrainConceptual model