mirror of
https://github.com/storytold/craft-libs.git
synced 2026-10-31 07:39:23 +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.
16 lines
1.4 KiB
Markdown
16 lines
1.4 KiB
Markdown
# AGENTS.md
|
|
|
|
Shared Rust libraries for the Craft Apps. The shared standards live in
|
|
[craftrules](https://github.com/storytold/craftrules) (`../../craftrules` on a dev machine): read its
|
|
`AGENTS.md`, then `standards/never-crash.md`, `standards/engineering.md` and `standards/licensing.md`.
|
|
|
|
- **Never crash.** Every crate's `lib.rs` starts with
|
|
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
|
No `unsafe` (the workspace forbids it).
|
|
- **New crates** go in `crates/<name>`, named `craft-<name>`, inherit the workspace package fields
|
|
and lints, and are listed in `[workspace.dependencies]`.
|
|
- **No app code.** A crate here must be useful to more than one app and must not depend on any app.
|
|
- **Time goes through `chrono`** (workspace dependency). Never hand-roll UTC/calendar conversion (days-to-date algorithms, leap-year math); a crate owns only its output format string. The one exception is range extension: past the years chrono can represent, shift the date by whole 400-year Gregorian cycles (146,097 days, after which the calendar repeats), let chrono compute the month and day, and add the cycles back to the year (splitting seconds into hours, minutes and seconds is plain arithmetic).
|
|
- **Before merging:** `cargo fmt --check`, `cargo clippy --workspace --all-targets -- -D warnings`,
|
|
`cargo test --workspace`.
|