calendar: compute real Easter dates and temporal-cycle seasons

resolveDay() no longer hardcodes season: 'trinitytide'. Easter is
computed via the Anonymous Gregorian algorithm (verified against 16
known reference dates spanning 1583-2100); Advent/Christmastide/
Epiphanytide follow the Christmas-anchored rules (including Advent's
"Sunday nearest Nov 30"); Septuagesima through Trinitytide come from
easter-offsets.yml, reshaped from single named anchor points into real
ranges plus single-day overrides for Corpus Christi and Sacred Heart.

occurring feasts (calendar/feasts.ts) are still a stub — the sanctoral
calendar and Double-vs-not ranking are a separate, larger project.
This commit is contained in:
2026-08-10 05:27:12 -04:00
parent 954edeb7b9
commit 67037469fc
8 changed files with 291 additions and 42 deletions
+27
View File
@@ -0,0 +1,27 @@
// Small ISO-date ("YYYY-MM-DD") arithmetic helpers shared by easter.ts and
// temporal.ts. Parsed/formatted as UTC midnight throughout, same convention
// as weekday.ts, so results don't shift with the caller's local timezone.
export interface CalendarDate {
year: number;
month: number; // 1-12
day: number;
}
export function toIsoDate(date: CalendarDate): string {
const mm = String(date.month).padStart(2, '0');
const dd = String(date.day).padStart(2, '0');
return `${date.year}-${mm}-${dd}`;
}
export function addDays(isoDate: string, days: number): string {
const d = new Date(`${isoDate}T00:00:00Z`);
d.setUTCDate(d.getUTCDate() + days);
return d.toISOString().slice(0, 10);
}
export function daysBetween(fromIsoDate: string, toIsoDate: string): number {
const from = new Date(`${fromIsoDate}T00:00:00Z`).getTime();
const to = new Date(`${toIsoDate}T00:00:00Z`).getTime();
return Math.round((to - from) / 86_400_000);
}