mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-03 09:11:10 +00:00
* Use chrono for UTC/calendar conversion instead of hand-rolled copies Replaces the hand-rolled civil_from_days and Day::to_days in crates/ai-core/src/history/report.rs with chrono, added as a workspace dependency (std-only, so ai-core still compiles for wasm). The day/month grouping, ISO and CSV timestamps and the Day/Month display are byte-identical and pinned by the existing tests. AGENTS.md now says time goes through chrono. Follow-up to storytold/cadcraft#1785 * history: preserve out-of-range conversion failure in civil_from_days civil_from_days used `i32::try_from(..).unwrap_or(0)` before calling NaiveDate::from_num_days_from_ce_opt, so a CE day count past i32 (e.g. from Day::from_days(i64::MAX)) passed a valid day 0 to chrono and read as 0000-12-31 instead of the 0000-01-01 fallback the None arm gives for every other out-of-range date. Convert with `.ok().and_then(..)` so both the integer-conversion and NaiveDate-construction failures share the one fallback. Regression test covers i64::MAX and i64::MIN. Doc comments on the chrono-touched to_days/from_days/civil_from_days now state the out-of-range behaviour (0 / 0000-01-01) for the docstring gate. * Convert every i32 year, not only chrono's range Day holds any i32 year, but NaiveDate stops near ±262143, so years like 262144 read as 0 / 0000-01-01. The Gregorian calendar repeats every 400 years: chrono now converts the day within its cycle and whole cycles are added back, in both directions. Values match the pre-chrono formula (tested for 262144, -262145, i32::MAX and i32::MIN). Nonexistent days still read as 0, and day counts whose year doesn't fit i32 still read as 0000-01-01. * Name the 400-year range extension as the one exception to the time rule The rule said never to hand-roll calendar math, but the range fix (shifting by whole 400-year Gregorian cycles so dates past chrono's year range keep their old output) is cycle arithmetic, so the rule and the code disagreed. The rule now names that exception: the library still computes month, day and time, and only whole cycles are carried in the year. * Say the library computes month and day; time-of-day is plain arithmetic Narrows the range-extension wording: the date library computes the calendar fields, and splitting seconds into hours, minutes and seconds is ordinary arithmetic, which is what the code does.