add Calendar + CalendarTime + Rhythm + LocalDate/Time as first-class

Phase 1.5 of time-system. Calendar is pluggable: EarthCalendar
(IANA zones, DST, Gregorian) is the default; MarsCalendar,
CycleCalendar(period), NoCycleCalendar handle non-Earth cases.

Rhythm abstracts recurrence from clock units - rhythm_cycle_phase(0.5)
means "midpoint of cycle" whether the cycle is 24 hours on Earth or
30 hours on a station or 300 years on a long-cycle world.

Phase 1 (Instant + Duration) unchanged. EarthCalendar(zone_local())
is the user-facing default; nobody who doesn't care about non-Earth
calendars sees the abstraction.

Self-host fixed point holds at 6339 lines.
Snapshot tagged at dist/platform/elc.20260502-1321-self-host.

Phase 2 (scheduling primitives every/after/at) lands next, now with
Calendar-aware grounding instead of Earth-time hardcoded.

Backlog: bl-297f66d8 (supersedes bl-b29b3e60)
This commit is contained in:
Will Anderson
2026-05-02 13:21:43 -05:00
parent e7c2fd02df
commit ed564b6dda
17 changed files with 1627 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
// earth-zone.el EarthCalendar(zone) formats with the right zone abbreviation.
// We use a fixed Instant on July 4, 2026 (definitely EDT in NYC) so the
// abbreviation is deterministic across runs.
fn run_test() -> String {
let z: Zone = zone("America/New_York")
let cal: Calendar = earth_calendar(z)
// 2026-07-04 12:00:00 UTC = 2026-07-04 08:00:00 EDT
let i: Instant = unix_seconds(1782216000)
let ct: CalendarTime = in_calendar(i, cal)
return cal_format(ct, "z")
}
fn main() -> Void {
println(run_test())
}