Skip to main content

Crate timeglyph

Crate timeglyph 

Source
Expand description

timeglyph — forensic timestamp decipherment.

A timestamp is time inscribed as a symbol — the raw integer or bytes a system writes to mean an instant. This crate deciphers those inscriptions: it decodes a known format to an instant, encodes an instant to any format, and — the differentiator — identifies an unknown value by reporting every plausible interpretation, scored, with stated assumptions, never “the answer” (a single integer is usually underdetermined).

§Design (see docs/decisions/ for the ADRs)

  • Canonical spine: PosixNs — nanoseconds since the Unix epoch, proleptic Gregorian, leap-second-ignoring (POSIX). It is not called UTC: UTC has discontinuities POSIX pretends away. Leap-aware scales (TAI/GPS/NTP) get their own instant types (to be added behind a hifitime feature).
  • Calendar/tz math is reused (jiff), never reinvented. The value-add is the cited forensic format registry + scored auto-detection + byte decode.
  • Panic-free (Paranoid Gatekeeper): every length/offset/width is checked.

§Example

// Identify an unknown value: every plausible reading, ranked and scored —
// never a single verdict (a raw value is usually underdetermined).
let candidates = timeglyph::interpret::interpret_int(1_577_836_800);
let top = &candidates[0];
assert_eq!(top.format_id, "unix");
assert_eq!(top.rendered.as_deref(), Some("2020-01-01T00:00:00Z"));

// Or decode under one known format by id.
let filetime = timeglyph::format("filetime").unwrap();
let instant = filetime.decode_int(132_223_104_000_000_000).unwrap();
assert_eq!(instant.to_rfc3339().as_deref(), Some("2020-01-01T00:00:00Z"));

§Further reading

The authoritative, primary-source-cited reference for every supported format — epochs, encodings, calendars, leap seconds, and the rollovers that eventually break them — lives at https://securityronin.github.io/timeglyph/.

Re-exports§

pub use datefmt::DateStyle;
pub use localzone::resolve_local;
pub use localzone::LocalResolution;

Modules§

cal
Bounded carve: find timestamps at every offset of a raw byte blob (identify_bytes swept over offsets, window + score-thresholded). Forensic calendar: civil facts of a date (ISO week, day-of-year, JDN/MJD, Unix midnight, weekday), the base of the cal subcommand. timeglyph cal — a forensics-grade calendar. This module is the pure data builder: [build_day] computes the civil + timezone facts of a date (ISO week, day-of-year, Julian Day Number, Modified JD, Unix midnight, weekday, per-day UTC offset, DST fold/gap, and — behind the leap feature — leap-second days and GPS week) with zero I/O, so it is fully testable and serialisable. Alternative calendars, the moon/season visual layer, rendering, and the CLI live in sibling modules built on top of this.
cal_art
ASCII art (moon discs, seasonal tiles) for the cal visual layer. ASCII art for the cal visual layer: moon-phase discs and seasonal scene tiles. These are a rendering of values computed in crate::cal (the phase index, the season) — never a value themselves — so the art is a pure lookup keyed by an integer, snapshot-tested under the tier-1 astronomy tests. @ = lit, . = dark; single-width ASCII only (no box-drawing).
cal_render
Pure text renderers for the cal month grid. Pure renderers for crate::cal — turn a [CalMonth] into a monospace text calendar for the terminal. No I/O, no colour side effects here: the grid uses spaces only (never box-drawing characters, which misalign across fonts), one marker glyph per day, and an ISO-week gutter. Machine (--json) output is the serde serialisation of CalMonth/CalDay, not produced here.
carve
Bounded carve: slide identify_bytes over a blob and report scored hits per offset — the validatable core of “find timestamps in raw bytes” (a malware config blob, a hex selection, one record).
compose
Composite (two-word) timestamp decode: values split across two integer fields. Some artifacts store a timestamp as two halves rather than one integer — a FILETIME as its dwLowDateTime/dwHighDateTime DWORDs in .reg exports, IE index.dat cookies, and packed malware configs. This reassembles the halves and decodes via the canonical single-value path, so the same epoch math applies. No single-value converter reconstructs these.
csv_enrich
CSV enrichment: add human-readable timestamp columns to a CSV.
datefmt
Datetime display styles shared by the CLI and the timeglyph-lens overlay.
holiday
Whole-world public-holiday lookup (ISO-3166 country + date → holiday name), behind the holiday feature. An embedded python-holidays export; a hit is “consistent with a public holiday”, an annotation rather than a guarantee. Whole-world public-holiday lookup, behind the holiday feature.
interpret
Auto-detection: identify an unknown value by reporting EVERY plausible interpretation, scored, with stated assumptions — never “the detected format.” A single integer is usually underdetermined: a 64-bit value can be a plausible Unix-s, Java-ms, Chrome-µs, FILETIME, .NET-ticks and Cocoa-s date all at once. Presenting one as the answer would fabricate certainty, which a forensic tool must never do (epistemics: “consistent with”, not a verdict).
leap
Leap-aware time scales (GPS/TAI/NTP), behind the leap feature. Kept separate from the POSIX PosixNs spine (ADR 0003). Leap-aware time scales — GPS, TAI64, NTP — deliberately kept OUT of the PosixNs spine (ADR 0003). GPS and TAI are genuinely leap-aware: their UTC rendering applies the IERS leap-second table via the hifitime crate (leap math is solved; we do NOT reinvent it). NTP follows UTC and does NOT count leap seconds, so its conversion is additive (reused via jiff); it is grouped here for the era-rollover handling, not for leap math.
localzone
Resolve a LocalNaive wall-clock value in a concrete zone — DST fold/gap (correctness wave). Pure over the IANA tzdb. Interpreting a LocalNaive wall-clock value in a concrete zone.
lunisolar
Chinese lunisolar calendar + 干支 four-pillar rendering, behind the lunisolar feature. Convention-relative: needs a meridian (and optional longitude), unlike the instant↔instant rest of the crate. Chinese lunisolar calendar + 干支 (Heavenly-Stem / Earthly-Branch) four-pillar rendering, behind the lunisolar feature.
mcp
MCP (Model Context Protocol) stdio JSON-RPC handler — expose the engine as tools for LLM-driven DFIR (cited readings, not hallucinated epoch math). MCP (Model Context Protocol) JSON-RPC handler over stdio. Exposes the engine as tools — identify, decode, explain — so an LLM-driven DFIR workflow gets a cited, reproducible reading instead of a hallucinated epoch conversion (LLMs are reliably wrong at FILETIME↔Unix arithmetic). The handler is a pure function; the mcp subcommand is a thin stdin→[handle]→stdout loop over it.
registry
The forensic format registry — the ENGINE half of the knowledge/engine split.
scan
Scan arbitrary text for timestamp candidates and decode each into ranked readings (the CLI scan command and the timeglyph-lens overlay share this). Scan arbitrary text for timestamp candidates and decode each into ranked readings. Three extractors — long digit runs ([scan_numbers]), self-describing datetime strings ([datetime_candidates]), and raw-hex tokens ([hex_candidates]) — feed interpret; [inspect_text] ties them together. Pure and GUI-free: it powers both the CLI scan command and the timeglyph-lens overlay.

Structs§

Format
One forensic timestamp format: the authoritative catalog record (meta, the evidence metadata + Encoding, owned by forensicnomicon) plus the engine’s packed codec when the encoding is Encoding::Packed. Derefs to meta, so f.id, f.citation, f.tz, f.encoding, … read straight through to the catalog entry.
PosixNs
The canonical internal instant: nanoseconds since 1970-01-01, POSIX (leap-ignoring), proleptic Gregorian. i128 because some source epochs sit
TimeFormat
One forensic timestamp format: evidence metadata, not just a converter.

Enums§

ChronoError
Errors from decoding, encoding, or rendering a timestamp.
Encoded
The natural encoded value of a format: an integer (linear / embedded / packed) or a float (OLE / Julian / Excel / Cocoa double). Displays as the bare value.
Encoding
How a stored value maps to an instant. The engine reads this to decode.
LeapSemantics
Leap-second semantics. Most forensic epochs are POSIX (leap-ignoring); only the GPS/TAI/NTP family needs true leap math (handled by the engine’s separate leap-aware instant type).
PackedLayout
Identifies which packed bit-field layout an Encoding::Packed format uses. A packed timestamp is not a linear offset but calendar fields squeezed into an integer, so decoding it needs a dedicated unpacker. The knowledge table names the layout here; the engine (timeglyph) dispatches this tag to the unpacker that does the (calendar-aware) math.
RenderZone
A target timezone for rendering an instant (PosixNs). Presentation only — it never changes the underlying instant, just how it is displayed. The default (RenderZone::Utc) renders with a Z suffix.
TzSemantics
Timezone semantics of a format’s stored value — NOT garnish: FAT stores local time, EXIF often lacks an offset, Event Logs store UTC but display local.
Unit
The tick unit a linear/embedded format counts in.

Constants§

VERSION
The engine’s version (CARGO_PKG_VERSION), for callers that surface it — e.g. the timeglyph-lens overlay’s landing screen.

Functions§

format
Look up a registered format by id.
registry_digest
A deterministic 16-hex-character fingerprint of the format registry — each entry’s id and citation, in catalog order. The provenance anchor for --provenance: the same engine build always yields the same digest, and any change to a format definition changes it, so a reading is traceable to the exact method version that produced it. Pure FNV-1a (no dependency). Iterates the authoritative forensicnomicon catalog (the source the engine wraps).