chrono-node-rs 0.1.0

Behaviour-matched Rust port of chrono-node: natural-language date parsing, checked against chrono-node's own output
Documentation

chrono-node-rs

A behaviour-matched Rust port of chrono-node by Wanasit Tanakitrungruang, the JavaScript library that finds dates and times in plain text ("tomorrow at 5pm", "next Friday at noon"). All credit for the parsing rules goes to chrono-node and its author; this crate is an independent port, not an official chrono-node release. chrono-node is MIT-licensed, and its copyright and licence notice are kept in NOTICE, which ships with the crate.

The port follows upstream closely, file by file, and is checked against chrono-node's own output:

  • Golden tests: chrono-node's own test cases, with outputs recorded by running the real chrono-node.
  • Random-phrase comparison: a harness runs generated phrases through both chrono-node and this crate and requires the same answers.
  • Nightly monitor: every night, fresh random phrases in every ported language are compared between main and chrono-node; any mismatch is filed as a bug with a reproducible seed.

It ports a pinned upstream release: chrono-node v2.10.3 (commit d4fe7e3). The copy is kept unmodified in upstream/; see upstream/PINNED.md.

Status

As of 2026-11-10, all 16 of chrono-node's locales are ported, plus the shared code (zh as zh.hans and zh.hant):

Locales How they were ported
Common code, en, de, fr, sv, pt, es, ja Factory v1, in waves
fi, id, nl, ru, uk, ar, zh.hans, zh.hant Factory v1 with generated onboarding: a generator records each language's golden cases and contracts from the pinned chrono-node, and the factory onboards the next language as soon as the previous one's tasks close
vi A/B experiment: a separate goal-driven agent session, outside the factory's task automation (#491, #495–#500)
it Factory v2 pilot: one agent run for the whole language (#553; results in docs/factory-v2.md)

Every locale passes the same checks on main, whichever way it was ported:

  • Golden cases: 2,675 of chrono-node's own test cases, 0 pending (tests/golden/).
  • Golden frontier: each ported parser and refiner is checked on its own against chrono-node's output, on every case. The check also confirms that every language has every step ported, with no case left pending (harness/golden/frontier.js; the run at completion: ci #42744564299).
  • Random-phrase comparison: generated phrases run through both chrono-node and this crate, with the same answers required (comparison harness). At the v2 pilot, 10,000 phrases per language (170,000 in all, seed 20261110) had 0 mismatches.
  • Nightly monitor: fresh random phrases in every language, every night (monitor runs).

The crate isn't published to crates.io yet. 0.1.0 is the first planned release.

Usage

[dependencies]
chrono-node-rs = "0.1"   # the library is imported as `chrono_node`; needs Rust 1.85 or later
use chrono_node::{configuration, parse, parse_date, JsDate, ParsingOption, ReferenceInput};

let reference = ReferenceInput::Date(JsDate::parse_iso("2012-08-10T09:00:00.000Z").unwrap());

// English (casual), like chrono.parseDate and chrono.parse
let date = parse_date("tomorrow at 5pm", &reference).unwrap();
assert_eq!(date.to_iso_string().unwrap(), "2012-08-11T17:00:00.000Z");

let results = parse("Let's meet next Friday at noon", &reference);
assert_eq!(results[0].text, "next Friday at noon");
assert_eq!(results[0].date().to_iso_string().unwrap(), "2012-08-17T12:00:00.000Z");

// Other locales by name: "de.casual", "fr.strict", "en.GB.casual", ...
let de = configuration("de.casual").unwrap();
let results = de.parse("morgen um 10 Uhr", &reference, &ParsingOption::default());
assert_eq!(results[0].date().to_iso_string().unwrap(), "2012-08-11T10:00:00.000Z");

The system time zone is always UTC: a reference without a time zone is read as UTC. How the JavaScript is translated, and why, is in PORTING.md.

Build and test

Needs the Rust toolchain in rust-toolchain.toml (rustup picks it up).

cargo build
cargo test                       # unit, configuration, golden and doc tests
cargo test --test golden         # just the golden tests

The golden tests in tests/golden/ are chrono-node's own test cases, with outputs recorded by running the real chrono-node. The comparison harness in harness/ (Node 24+) also runs random phrases through both chrono-node and the Rust CLI chrono-rs-json and compares the answers:

cd harness && npm ci && npm run build:upstream
cargo build && npm run compare -- --rust ../target/debug/chrono-rs-json

See harness/README.md for seeds and options.

How it's built

Each change is made by an AI agent through the factory, and is checked against chrono-node's own output before it merges. Agents can't edit the contracts, golden tests, harness or workflows.

Licence

MIT, see LICENSE. Parts of src/ are translations of chrono-node (MIT, Copyright (c) 2014 Wanasit Tanakitrungruang); its full licence notice is in NOTICE, included in the published crate.