← Tepna preprints

Parsing time from the wild: a deterministic benchmark of consumer-export timestamp pathologies and the floating wall-clock model

Michal Planicka  ·  corresponding author — Tepna Project

Clock Contract (clock.js · DexClock), Tepna physiological-signal suite

Draft v1 · July 2026 · Analysis: timestamp-pathology-analysis.html (runs the production parser live) · Corpus: real vendor headers + synthetic edge cases · 100% local, deterministic

Abstract

Problem. Every downstream physiological result depends on getting one thing right that the literature almost never discusses: parsing the timestamp out of a consumer device export. Consumer exports carry a zoo of incompatible time formats — ambiguous day/month order, zoned versus zone-less stamps, bare epoch integers, compact 14-digit runs, and time-only rows that silently cross midnight — and the usual reflex (new Date(str) / Date.parse) resolves several of them wrongly but silently, or fabricates the current time when a stamp is missing. Contribution. We state a single time model — UTC-normalized floating wall-clock milliseconds (tMs) — as a citable method, and provide a deterministic pass/fail benchmark of the failure modes it must survive. The model stores each record's local civil time as if it were UTC (tMs = Date.UTC(components-as-written)), which makes displayed time independent of the viewer's timezone and makes two devices that recorded the same wall-clock minute produce the same tMs by construction. Result. The production parser resolves a corpus of 24 vendor/branch cases and upholds 6 contract invariants — viewer-timezone independence, zoned≡floating equivalence, deterministic DMY/MDY disambiguation, monotonic overnight roll, never-fabricate-on-miss, and epoch determinism — all green, regenerated live from the shipping code. Significance. This is a methods/reproducibility note, not a physiological finding; its value is a stated, testable standard for a step the field treats as an afterthought and a corpus others can run against their own parser.

Keywords: timestamp parsing · data provenance · wall-clock time · timezone · DMY/MDY ambiguity · ISO-8601 · epoch time · consumer wearables · reproducibility · cross-device synchronization

0. Layman overview (delete before submission)

Before you can say anything about someone's heart rate at 3 a.m., you have to know which moment “3 a.m.” actually was — and the little date-and-time text that devices write into their files is a mess. Some write the day first, some the month first (is 05/07 May 7th or July 5th?); some include a timezone, most don't; some write just a raw number of seconds; some write only the time and leave you to figure out the date. The lazy way to read these — hand the text to the computer's built-in date reader — quietly gets several of them wrong, and worst of all, when a stamp is missing it often just fills in “right now,” inventing data. This paper writes down one careful rule for reading all of these correctly, and a checklist of tricky cases it must pass. The key trick: store each reading as the wall-clock time the person actually saw, not tied to any timezone, so the same bedtime looks the same whether you open the file in New York or London, and two devices worn the same night line up automatically. We run the checklist against the real code: every case passes. It's plumbing, not a discovery — but it's the plumbing everything else stands on.

1. Introduction

Physiological analysis papers report what happened at a time; almost none report how the time itself was parsed. Yet consumer device exports — the raw material of at-home physiology — encode time in mutually incompatible ways, and the default tools resolve them inconsistently. A single archive can contain an O2Ring oximeter writing HH:MM:SS DD/MM/YYYY, a Welltory CSV writing MM/DD/YYYY HH:MM, a Polar sensor logger writing zoned ISO-8601, and a filename embedding a bare YYYYMMDDHHMMSS. Handing any of these to new Date(str) invokes locale- and engine-dependent heuristics: it may read a European 13/05 correctly by luck and an American 05/13 wrongly, attach the parsing machine's timezone to a stamp that had none, or — most dangerously — return the current time for an unparseable input, silently fabricating a data point.

The synthetic-data-frontier perspective explicitly named this as the series' "narrowest first paper." This is that paper. Its contribution is not an algorithm but a stated standard: a single time model, the failure corpus it must survive, and a live tool that proves the shipping parser survives it. We make three claims: (i) the correct canonical unit for zone-less consumer physiology is a floating wall-clock, not a real UTC instant; (ii) every vendor format maps into it deterministically by explicit regex, never by locale heuristics; and (iii) a missing or malformed stamp must resolve to null, never to a fabricated time.

2. Methods

2.1 The canonical unit — floating wall-clock tMs

Each record's local civil time is stored encoded as if it were UTC: tMs = Date.UTC(year, month−1, day, hour, min, sec, ms). This is deliberately not a real UTC instant. Consumer devices speak local civil time with no zone; storing a real UTC instant and rendering it with local getters would make displayed time depend on the viewer's timezone (a New-York night reads 03:00 in London). Floating tMs read back with the getUTC* family is viewer-timezone-independent, and two devices recording the same wall-clock minute yield the same tMs by construction — so cross-device synchronization holds without either device sharing a timezone. An optional offsetMin is captured only when the input carried a real zone; the true instant is then recoverable as tMs − offsetMin·60000, but all sorting, alignment and display default to tMs.

2.2 Resolution order (the parser)

The single parser DexClock.parseTimestamp(raw, opts) resolves in a fixed priority, each branch an explicit regex — never Date.parse on a vendor string: (1) numeric epoch (10–13 digits or numeric type, plausible-range gated), localized to the parse-time zone; (2) ISO-8601 with zone — zone authoritative, re-expressed as wall clock with offsetMin captured; (3) ISO / YYYY-MM-DD[ T]HH:MM[:SS] without zone — components verbatim, offsetMin=null; (4) explicit vendor formats — HH:MM:SS DD/MM/YYYY (O2Ring), 14-digit compact, DD/MM/YYYY HH:MM (Welltory), YYYY/MM/DD HH:MM:SS; (5) time-only HH:MM[:SS] combined with a date anchor and rolled forward monotonically past each midnight; (6) fallback → null, never now().

2.3 DMY vs MDY disambiguation

Any row whose day-field exceeds 12 makes the file unambiguous, and that order is locked for the whole file; otherwise the caller's preferDMY hint decides (default true for O2Ring/Welltory, false for the CGM MDY convention). The order is never switched mid-file.

2.4 Benchmark construction

The corpus (Table 1) has one entry per parser branch and per vendor format observed in the suite's real exports, plus adversarial edge cases (implausible epoch, partial date, empty, garbage, anchorless time-only). The invariants (Table 2) encode the contract's behavioural guarantees. Both run against the production clock.js in timestamp-pathology-analysis.html; the pass counts below are read from that tool's live output (window.__tsbench).

3. Results

The production parser resolved 24 / 24 corpus cases and upheld 6 / 6 contract invariants — all green, regenerated live from the shipping code.

Table 1. Vendor / branch corpus (representative rows; full 24-case set regenerates in the analysis tool). float marks a zone-less floating stamp (offsetMin=null).
CategoryRaw inputResolves toNote
Epoch"1751925600000"instant + offsetMin13-digit ms; 10-digit s auto-scaled
Epoch (bad)"999"nullbelow plausible range
Zoned ISO"…22:00:00+02:00"22:00 wall, off=120zone in offsetMin, wall kept
Floating ISO"2026-07-07 22:00"22:00 floatno zone → offsetMin=null
O2Ring"22:40:01 07/07/2026"2026-07-07 22:40:01HH:MM:SS DD/MM/YYYY
Compact"20260707224001"2026-07-07 22:40:0114-digit filename embed
Welltory"07/05/2026 21:53"May 7 (DMY) / Jul 5 (MDY)preferDMY switch, per-file locked
Time-only"00:15" (prev 23:55)next-day 00:15monotonic midnight roll
Time-only (bad)"23:30" (no anchor)nullnever Jan-1-2000
Malformed"" / "not a date" / nullnullnever now()
Table 2. Clock Contract invariants — the behavioural guarantees the model exists to provide. All hold against the shipping parser.
InvariantHoldsWhat it guarantees
B1 · viewer-timezone independencefloating path is pure Date.UTC, no getTimezoneOffset → identical tMs on any machine
B2 · zoned wall ≡ floating walla zoned and a zone-less stamp for the same wall instant give the same tMs; zone lives only in offsetMin
B3 · DMY 13/05 ≡ MDY 05/13a day-field >12 disambiguates the file deterministically, regardless of the hint
B4 · overnight monotonic roll22:00→06:00 time-only rows span 8 h, not a 24 h backward jump
B5 · never fabricate on missmissing / garbage / anchorless → null; the parser never returns now()
B6 · epoch determinismstring and numeric epoch inputs resolve to the identical instant

Invariant B1 deserves a precise statement: only the floating branches (2–5) are viewer-timezone-independent, and by construction — they never call getTimezoneOffset. The epoch branch (1) does consult the runner timezone, deliberately, because a bare epoch is a genuine instant that must be localized to a wall clock; that is the one place the viewer's zone legitimately enters, and it is confined there.

4. Discussion

The practical lesson is that timestamp parsing is a correctness surface, not a convenience call, and that the default library path is actively unsafe for consumer physiology on three counts: silent DMY/MDY mis-resolution, spurious timezone attachment, and fabrication-on-miss. The floating wall-clock model neutralizes the first two by construction (components-as-written + getUTC* read-back) and the third by contract (miss → null). The model's non-obvious move — storing local civil time as if UTC rather than as a real instant — is what buys viewer-timezone independence and zero-configuration cross-device alignment, the two properties every multi-signal result in this suite silently relies on. Because the benchmark is a live tool over the shipping parser rather than a frozen table, it doubles as a regression guard: any future parser change that breaks a vendor format or an invariant turns the tool red.

Limitations. This is a methods/reproducibility note, not a physiological result — it asserts correctness of parsing, not accuracy of any downstream metric. The corpus is representative of the formats observed in this suite's real exports plus constructed adversarial cases; it is not an exhaustive enumeration of all consumer vendor formats in existence, and new devices will add branches (the vendor-adapter layer, when it lands, only widens the corpus — it does not change the model). The DMY/MDY rule is deterministic but cannot rescue a file that is genuinely ambiguous in every row (all day-fields ≤12) beyond honoring the caller's declared convention. Epoch localization is correct only to the parse-time machine zone, which is the intended and only available behavior for a bare instant.

5. Reproducibility

6. References

  1. Perspective that teed up this paper: papers/synthetic-data-frontier.html — names the timestamp benchmark as the narrowest first paper.
  2. Project documentation: CLAUDE.md §🔒 The Clock Contract — the normative specification this paper benchmarks.
  3. ISO 8601-1:2019. Date and time — Representations for information interchange.
  4. ECMAScript Language Specification, Date.UTC / Date.prototype.getUTC* (the floating-time primitives used).