Validation¶
A forensic tool's output is only worth the rigour behind it. This page documents exactly how each timeglyph format is checked, against whom, and at what confidence tier — so the standing rests on measurements an independent party can re-run, not on self-assessment.
Evidence tiers¶
timeglyph classifies every validation by who confirms it (the fleet standard):
| Tier | Definition | Example here |
|---|---|---|
| Tier 1 | An independent third party authored both the input value and the answer, or it is real-world data. | Discord's docs give id 175928847299117063 → 2016-04-30 11:18:25.796; Apple TN1150 states HFS+ max = 2040-02-06 06:28:15. |
| Tier 2 | Real output checked against an independent oracle, but we chose the scenario. | A value we picked, confirmed by an independent implementation (e.g. CPython). |
| Tier 3 | We authored both the fixture and the expected answer, nothing independent vouches. | (Avoided — these are the self-deception trap.) |
The goal is tier 1 wherever reachable; tier-2 rows are labelled honestly.
Independent oracles¶
| Oracle | Author / license | Role | Verified |
|---|---|---|---|
| time-decode v10.4.0 | Corey Forman (digitalsleuth), MIT — github | A separate implementation of 73 timestamp formats; the primary differential oracle (the reference named in the project handoff). | run in this battery |
CPython datetime |
Python Software Foundation, PSF-2.0 — docs | Independent implementation for formats time-decode lacks a flag for (PostgreSQL, Unix-ns). | run |
| Format specifications | the spec authors (Discord, Microsoft, Apple, RFCs, …) | Spec worked examples: the author states value → answer directly (tier-1 gold). | see References |
Differential validation between two independent implementations is strong but not infallible — a shared misreading of a spec could make both agree on a wrong answer. The tier-1 spec worked examples below anchor the trickiest epochs independently of any tool, which is why both kinds of check are used together.
The differential battery¶
Every input below is time-decode's own published example value for that
format (time-decode --formats <fmt>), so the input is authored by the
independent third party — not chosen by us — and the expected answer is its
tool's output. timeglyph agrees with all of them to the second. The battery is
encoded as an env-gated test (tests/oracle.rs).
| timeglyph format | oracle flag | third-party input | agreed answer (UTC) | tier |
|---|---|---|---|---|
unix |
--unixsec |
1746371930 |
2025-05-04 15:18:50 | 1 |
unix_ms |
--unixmilli |
1746371930064 |
2025-05-04 15:18:50.064 | 1 |
unix_us |
--prtime |
1746371930064939 |
2025-05-04 15:18:50.064939 | 1 |
filetime |
--active |
133908455300649390 |
2025-05-04 15:18:50.064939 | 1 |
webkit |
--chrome |
13390845530064940 |
2025-05-04 15:18:50.064940 | 1 |
hfsplus |
--hfsdec |
3829216730 |
2025-05-04 15:18:50 | 1 |
hfsplus (max) |
--hfsdec |
4294967295 |
2040-02-06 06:28:15 | 1 (spec + oracle) |
dotnet_ticks |
--dotnet |
638819687300649472 |
2025-05-04 15:18:50.064947 | 1 |
cocoa_float |
--mac |
768064730.064939 |
2025-05-04 15:18:50.064939 | 1 |
sqlite_julian |
--juliandec |
2460800.1380787035 |
2025-05-04 15:18:49.999986 | 1 |
ole |
--oleauto |
45781.638079455312 |
2025-05-04 15:18:50.064939 | 1 |
discord |
--discord |
1102608904745127937 |
2023-05-01 14:54:08.374 | 1 |
snowflake |
--twitter |
1189581422684274688 |
2019-10-30 16:34:47.179 | 1 |
fat |
--fat |
a45a597a |
2025-05-04 15:18:50 (local) | 1 |
gps |
--gps |
1430407111 |
2025-05-04 15:18:13 | 1 |
ntp |
--ntp |
3981841662.020607 |
2026-03-07 03:07:42 | 1 |
tai64 |
--tai |
1599755800 |
2020-09-10 16:36:03 | 1 |
Formats time-decode has no flag for
postgres (µs since 2000) and unix_ns are validated against CPython
datetime instead, with values we chose — tier 2:
postgres 631152000000000 → 2020-01-01 00:00:00 and
unix_ns 1577836800000000000 → 2020-01-01 00:00:00. To reach tier 1, source
a third-party-published worked example for each.
Tier-1 spec worked examples¶
These come straight from the format's own specification — the author states the value and the answer, so no tool is involved:
- Discord — the developer docs decode
175928847299117063→2016-04-30 11:18:25.796 UTC(Discord docs). - OLE Automation — Microsoft states
2.0= 1900-01-01 and2.5= noon 1900-01-01 (VariantTimeToSystemTime). - HFS+ — Apple TN1150 states the maximum date is
2040-02-06 06:28:15 GMT(the u32 overflow), matched byhfsplus 4294967295(TN1150).
These are encoded in tests/anchors.rs and run on every build (no oracle needed).
Input conventions (reconciled divergences)¶
The same instant can be presented to a decoder in different encodings. Where timeglyph and the oracle take different encodings, the battery converts between them — these are convention differences, not disagreements about the time:
- FAT — time-decode reads the 4 on-disk bytes
a4 5a 59 7aasdate = LE(a4,5a) = 0x5AA4,time = LE(59,7a) = 0x7A59. timeglyph takes those two 16-bit words packed into one integer (date in the high word) =0x5AA47A59. Both decode to the same instant. - TAI64 — the external label is
2^62 + s(s = TAI seconds since 1970 TAI), while time-decode's--taitakessdirectly; the battery passeslabel − 2^62. - NTP — time-decode's example carries a fractional part (
….020607); timeglyph decodes the integer seconds field. They agree to the second.
The broader question of robustly handling endianness, hex-vs-decimal, and packed layouts is a design topic tracked separately.
How to run¶
# 1. Install the independent oracle (MIT).
pip install time-decode
# 2. Run the env-gated differential battery (skips cleanly if absent).
cargo test --features leap --test oracle
# 3. The tier-1 spec anchors run with the normal suite.
cargo test --all-features
Appendix — epoch offsets (seconds to the Unix epoch)¶
A cross-check reference; positive = after 1970, negative = before.
| Epoch | Used by | Offset to 1970 |
|---|---|---|
| 0001-01-01 | .NET ticks | −62 135 596 800 s |
| 1582-10-15 | UUIDv1/v6 | −12 219 292 800 s (×10⁷ as 100-ns) |
| 1601-01-01 | FILETIME, WebKit | −11 644 473 600 s |
| 1899-12-30 | OLE Automation | −2 209 161 600 s |
| 1900-01-01 | NTP | −2 208 988 800 s |
| 1904-01-01 | HFS+ | −2 082 844 800 s |
| 1970-01-01 | Unix | 0 |
| 1980-01-01 | FAT/DOS | +315 532 800 s |
| 1980-01-06 | GPS | +315 964 800 s |
| 2000-01-01 | PostgreSQL | +946 684 800 s |
| 2001-01-01 | Cocoa / CFAbsoluteTime | +978 307 200 s |
Julian Day 2440587.5 = the Unix epoch. Leap offsets (2017→): TAI − UTC = 37 s,
GPS − UTC = 18 s. See Time scales and
Calendars.