Implement the resumed-post-Epiphany-Sunday temporal-id algorithm
Deploy / deploy (push) Successful in 1m6s

Post-Pentecost overflow years (early Easter, fewer than 6 Sundays after
Epiphany fit before Septuagesima) previously clamped every excess Sunday
to post-pentecost-24 instead of resuming the skipped post-Epiphany
Sundays' own content, per the traditional rubric. Ported directly from
the reference engine's own DivinumOfficium/Date.pm getweek().

Also adds the Epiphany VI Saturday-before-Septuagesima commemoration
(only when Epiphany V was the last Sunday to actually occur), and fixes
day-label.ts's on-screen display to track the same resumed-Sunday
content instead of a raw elapsed-week count — including a correction so
the fixed final Sunday of the year always reads "23rd Sunday after
Trinity", not a per-year-varying number.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 20:07:04 -04:00
parent f811fcc8f6
commit a7901b3c61
6 changed files with 255 additions and 25 deletions
+63 -12
View File
@@ -22,10 +22,6 @@ across every hour and content type in this app.
- Pre-1955-but-post-1617 saints' differently-structured Matins readings — source confirmed - Pre-1955-but-post-1617 saints' differently-structured Matins readings — source confirmed
(Tridentine/Divino Afflatu, combine-where-sensible applies the same way), but the actual (Tridentine/Divino Afflatu, combine-where-sensible applies the same way), but the actual
sourcing/modeling pass hasn't started — see "Matins ordo" below. sourcing/modeling pass hasn't started — see "Matins ordo" below.
- The "which Sunday governs this date" temporal-id algorithm (23rd-Sunday-before-Advent
rule, Epiphany-Sunday transfer to the end of the liturgical year, the
Saturday-before-Septuagesima 6th-Epiphany-Sunday commemoration edge case) — tabled, not
started.
- Easter's own octave — tabled, "a whole different discussion." - Easter's own octave — tabled, "a whole different discussion."
- What "a Gospel reading is its own kind" should mean structurally/in the UI, beyond the - What "a Gospel reading is its own kind" should mean structurally/in the UI, beyond the
`isGospel` flag on a plain Matins `lesson` — open; deferred until there's a UI to `isGospel` flag on a plain Matins `lesson` — open; deferred until there's a UI to
@@ -1460,17 +1456,72 @@ seasonally variable — what's stored is whichever form rendered live on
each one's already-chosen clean query date, not a season-aware each one's already-chosen clean query date, not a season-aware
substitution. Same class of gap as the Paschaltide alleluia suffix substitution. Same class of gap as the Paschaltide alleluia suffix
elsewhere in this file, flagged not fixed. elsewhere in this file, flagged not fixed.
- **The "which Sunday governs this date" temporal-id algorithm** — the fixed
23rd-Sunday-before-Advent rule, Epiphany Sundays transferring to the end
of the liturgical year when they don't fit before Septuagesima, and the
Saturday-before-Septuagesima edge case (also commemorate the 6th Sunday
of Epiphany that day, in overflow years). Described in detail in an
earlier conversation, explicitly tabled, not started. Distinct from
Christ the King, which didn't need it (last-Sunday-of-October is direct
date math).
- **Easter's own octave** — explicitly tabled ("easter needs a whole - **Easter's own octave** — explicitly tabled ("easter needs a whole
different discussion"). different discussion").
### The "which Sunday governs this date" temporal-id algorithm — done (2026-08)
Overflow years (Easter early enough that fewer than 6 Sundays after Epiphany occur before
Septuagesima cuts in) previously just clamped every excess post-Pentecost Sunday to
`post-pentecost-24` — wrong for every week between XXIII and the real last Sunday of the
year, only accidentally right for that final Sunday itself.
`calendar/temporal-id.ts`'s post-Pentecost branch is now ported directly from the reference
engine's own `getweek()` (`DivinumOfficium/Date.pm`) rather than re-derived by hand: once the
governing Sunday's Pentecost week reaches XXIII, a `wdist` (weeks until Advent) calculation
decides the id — the fixed final Sunday (`wdist < 2`) always resolves to `post-pentecost-24`
regardless of the true elapsed count, `post-pentecost-23` covers its own normal week, and
everything else resumes as `post-epiphany-${8 - wdist}` — the skipped post-Epiphany Sundays,
in their own ascending order, immediately before the fixed final Sunday. No separate tracking
of "how many post-Epiphany Sundays occurred" is needed — it falls out of the Advent-distance
arithmetic alone, confirmed against the reference engine's source rather than assumed. Trinity
Sunday = `post-pentecost-01` (this app's existing convention) also confirmed correct against
the same source (`$n=1` at `easter+56`, matching `TemporaM/Pent01-0.txt`'s own Trinity-Sunday
content).
Separately, `calendar/index.ts` gained `applyEpiphany6Commemoration`, an `apply*`-pass
(same shape as `applyChristTheKing`) that commemorates `post-epiphany-6` on the Saturday
immediately before Septuagesima — but only in years where Epiphany V (not IV, III, ...) was
the last post-Epiphany Sunday to actually occur, per direct clarification (a narrower rule
than "any skipped Sunday gets a Saturday commemoration" — only VI specifically, and only in
that one adjacency case). No new `Commemoration` variant was needed: the existing
`{ kind: 'temporal'; id }` shape already round-trips through `getDayCollects`'s
`${id}-collect` lookup for free, so this is purely additive to `commemorations`, coexisting
with whatever else that Saturday already resolved to (consistent with this app's generous,
non-single-winner commemoration design elsewhere).
Verified live against real years, not just unit-tested: 2026 (`post-epiphany-5` is the last
Sunday reached, so `2026-11-14`/`-21` resume as Epiphany V/VI before `2026-11-28`'s fixed
`post-pentecost-24`), and 1943/1962 (Easter late enough that all 6 Epiphany Sundays occur, so
no resumption and no Saturday commemoration ever fires). New test file
`tests/calendar/temporal-id.test.ts` covers both the overflow resumption and the Saturday
commemoration's on/off cases (2026, 2022, 2025, 1943). `npm test` (363 tests, 4 new) and
`npm run build` both pass.
**Follow-up done same day:** `calendar/day-label.ts`'s on-screen display now also tracks the
resumed-Sunday content, via a `trinitytideOverrideLabel` check ahead of the ordinary
Trinity-counted branch — it calls `resolveTemporalId` directly (the same mechanism the content
layer trusts) rather than re-deriving the wdist arithmetic a second time, so the label can
never disagree with what's actually rendered underneath. A resumed Sunday/weekday now reads
"The 5th Sunday after Epiphany" / "Monday in the 5th week after Epiphany" instead of continuing
the Trinity count past its real bound.
**Correction, same pass**: the first cut of this left the fixed final Sunday of the year
(`post-pentecost-24`) on the old raw "weeks since Trinity" arithmetic, on the assumption that
was an unrelated, already-correct convention — wrong. Scanning every year 1900-2100 showed
*every single year's* last Sunday before Advent resolves to `post-pentecost-24`, and the raw
elapsed-week count for that Sunday varies year to year (22nd, 23rd, 25th, ... depending on
Easter's date) even though the content is always the same fixed formulary. Since this app's
Trinity-counted display is one week off from the Pentecost-counted id (Trinity Sunday itself =
`post-pentecost-01` = the display's own uncounted anchor), the correct display ordinal for
that fixed Sunday is XXIV 1 = **23, always** — not derived from elapsed weeks at all.
`trinitytideOverrideLabel` now handles this as its own branch (`FIXED_LAST_SUNDAY_ORDINAL`),
same "ask `resolveTemporalId`, don't re-derive" principle as the resumed-Epiphany branch.
Live-verified across 1943/1962/2015/2026/2033 — all five now read "The 23rd Sunday after
Trinity" for their own last Sunday, where before the fix they'd shown four different numbers.
Tests in `tests/calendar/day-label.test.ts` updated accordingly. `npm test` (365 tests) and
`tsc --noEmit` both pass.
## Known, deliberate simplifications (not bugs — working as designed) ## Known, deliberate simplifications (not bugs — working as designed)
- `getDayCollects`: each collect in a multi-collect day renders as its own - `getDayCollects`: each collect in a multi-collect day renders as its own
+60
View File
@@ -15,6 +15,7 @@ import { adventStart, firstSundayStrictlyAfter, sundayOnOrBefore } from './tempo
import { addDays, daysBetween, toIsoDate } from './date-math'; import { addDays, daysBetween, toIsoDate } from './date-math';
import { getTemporalFeastRecord } from './temporal-feasts'; import { getTemporalFeastRecord } from './temporal-feasts';
import { resolveActiveOctave, type ActiveOctave } from './octaves'; import { resolveActiveOctave, type ActiveOctave } from './octaves';
import { resolveTemporalId } from './temporal-id';
function capitalize(text: string): string { function capitalize(text: string): string {
return text.charAt(0).toUpperCase() + text.slice(1); return text.charAt(0).toUpperCase() + text.slice(1);
@@ -109,7 +110,66 @@ function anchorDayName(day: LiturgicalDay): string | undefined {
return undefined; return undefined;
} }
/** The fixed final Sunday of the liturgical year (temporal-id.ts's
* `post-pentecost-24`) always carries "Sunday XXIV after Pentecost"'s own
* formulary, regardless of how many Sundays actually elapsed since
* Trinity — confirmed by scanning every year 1900-2100, every single one
* lands on this id for its own last Sunday before Advent, never a raw
* elapsed-week count. This app's Trinity-counted display is one week off
* from that Pentecost-counted id (Trinity Sunday itself = post-pentecost-
* 01 = the display's own uncounted anchor day), so the fixed display
* ordinal here is XXIV - 1 = 23, not whatever a plain "weeks since
* Trinity" calculation would produce. */
const FIXED_LAST_SUNDAY_ORDINAL = 23;
/**
* Trinitytide's ordinal display can't be pure "weeks since Trinity's own
* first Sunday" arithmetic once the season gets late enough — see
* temporal-id.ts's own post-Pentecost-XXIII-plus branch. Two cases, both
* driven by `resolveTemporalId` directly (the same mechanism the content
* layer already trusts, rather than re-deriving the wdist arithmetic here
* a second time, so the label can never disagree with what's actually
* rendered underneath):
* - A resumed post-Epiphany Sunday/week (an overflow year's skipped
* Epiphany Sundays, reappearing here) — reads "after Epiphany", not
* the next Trinity-counted number in line.
* - The fixed final Sunday/week of the year itself — always the fixed
* 23rd-after-Trinity ordinal (see FIXED_LAST_SUNDAY_ORDINAL above),
* every year, not just overflow ones.
* Only ever fires within trinitytide, since that's the only season
* resolveTemporalId can return either of these ids for a date outside
* their own native season.
*/
function trinitytideOverrideLabel(day: LiturgicalDay): string | undefined {
if (day.season !== 'trinitytide') {
return undefined;
}
const id = resolveTemporalId(day.date);
const weekdayName = capitalize(day.weekday);
const epiphanyMatch = id.match(/^post-epiphany-(\d)$/);
if (epiphanyMatch) {
const n = Number(epiphanyMatch[1]);
return day.weekday === 'sunday'
? `The ${ordinal(n)} Sunday after Epiphany`
: `${weekdayName} in the ${ordinal(n)} week after Epiphany`;
}
if (id === 'post-pentecost-24') {
return day.weekday === 'sunday'
? `The ${ordinal(FIXED_LAST_SUNDAY_ORDINAL)} Sunday after Trinity`
: `${weekdayName} in the ${ordinal(FIXED_LAST_SUNDAY_ORDINAL)} week after Trinity`;
}
return undefined;
}
function temporalLabel(day: LiturgicalDay): string { function temporalLabel(day: LiturgicalDay): string {
const trinitytideOverride = trinitytideOverrideLabel(day);
if (trinitytideOverride) {
return trinitytideOverride;
}
const weekdayName = capitalize(day.weekday); const weekdayName = capitalize(day.weekday);
const config = ORDINAL_SEASONS[day.season]; const config = ORDINAL_SEASONS[day.season];
if (!config) { if (!config) {
+31 -1
View File
@@ -5,7 +5,8 @@ import { resolveTemporalId } from './temporal-id';
import { getSanctoralCandidatesFor } from './feasts'; import { getSanctoralCandidatesFor } from './feasts';
import { decideOccurrence, isAtLeast, type OccurrenceResult } from './commemorations'; import { decideOccurrence, isAtLeast, type OccurrenceResult } from './commemorations';
import { resolveCollision } from './collision'; import { resolveCollision } from './collision';
import { addDays } from './date-math'; import { addDays, toIsoDate } from './date-math';
import { easterSunday } from './easter';
import { activeOctavesFor, strictestThreshold } from './octaves'; import { activeOctavesFor, strictestThreshold } from './octaves';
/** /**
@@ -104,10 +105,39 @@ export function resolveDay(isoDate: string): LiturgicalDay {
winner = applyMarianSaturday(isoDate, weekday, temporalCategory, winner, commemorations); winner = applyMarianSaturday(isoDate, weekday, temporalCategory, winner, commemorations);
winner = applyChristTheKing(isoDate, winner, commemorations); winner = applyChristTheKing(isoDate, winner, commemorations);
winner = applyChristmasOctaveSunday(isoDate, weekday, winner, commemorations); winner = applyChristmasOctaveSunday(isoDate, weekday, winner, commemorations);
applyEpiphany6Commemoration(isoDate, commemorations);
return { date: isoDate, weekday, season, temporalCategory, winner, commemorations }; return { date: isoDate, weekday, season, temporalCategory, winner, commemorations };
} }
/**
* Real rubric, confirmed 2026-08: when the 6th Sunday after Epiphany is
* bumped by Septuagesima — i.e. only in years where the 5th Sunday after
* Epiphany was the last one to actually occur — it's commemorated on the
* Saturday immediately before Septuagesima, on top of whatever else that
* Saturday already resolved to. Distinct from (and doesn't imply) the
* later "resumed post-Epiphany Sunday" transfer handled in
* temporal-id.ts's post-Pentecost overflow branch — that one applies to
* *every* skipped post-Epiphany Sunday, not just VI; this Saturday
* commemoration is VI's alone. Purely additive: no `Commemoration` variant
* needed beyond the existing `{ kind: 'temporal' }` one, since
* hours/resolve-common.ts's getDayCollects already resolves any temporal
* commemoration's own `${id}-collect` for free.
*/
function applyEpiphany6Commemoration(isoDate: string, commemorations: Commemoration[]): void {
const year = Number(isoDate.slice(0, 4));
const septuagesimaStart = addDays(toIsoDate(easterSunday(year)), -63);
const saturdayBeforeSeptuagesima = addDays(septuagesimaStart, -1);
if (isoDate !== saturdayBeforeSeptuagesima) {
return;
}
const lastEpiphanySunday = addDays(septuagesimaStart, -7);
if (resolveTemporalId(lastEpiphanySunday) !== 'post-epiphany-5') {
return;
}
commemorations.push({ kind: 'temporal', id: 'post-epiphany-6' });
}
/** The Sunday on or before Oct 31 — always lands in October since Oct 31 /** The Sunday on or before Oct 31 — always lands in October since Oct 31
* is at most 6 days after the month's last Sunday. */ * is at most 6 days after the month's last Sunday. */
function lastSundayOfOctober(year: number): string { function lastSundayOfOctober(year: number): string {
+38 -12
View File
@@ -11,16 +11,23 @@
// header and propers/index.ts's getTemporalProper for the fuller version // header and propers/index.ts's getTemporalProper for the fuller version
// of this reasoning. // of this reasoning.
// //
// Two known, deliberately unfixed gaps: the ferias between Christmas Day // One known, deliberately unfixed gap: the ferias between Christmas Day
// and the Sunday within its octave, and between Epiphany and its own // and the Sunday within its octave, and between Epiphany and its own
// first Sunday, fall back to that season's first named Sunday a few days // first Sunday, fall back to that season's first named Sunday a few days
// early — Christmas Day's and Epiphany's own collects aren't authored as // early — Christmas Day's and Epiphany's own collects aren't authored as
// separate temporal-propers entries (only Sunday collects were pulled), so // separate temporal-propers entries (only Sunday collects were pulled), so
// this is a deliberate approximation, not an oversight. Likewise, a real // this is a deliberate approximation, not an oversight.
// overflow year (early Easter, more than 24 weeks between Trinity and //
// Advent) would traditionally reuse the unused post-Epiphany Sundays' // Overflow years (Easter early enough that fewer than 6 Sundays after
// collects for the excess weeks — not modeled; this just clamps at // Epiphany occur before Septuagesima cuts in) are handled below: the
// post-pentecost-24. // skipped post-Epiphany Sundays "resume" after Sunday XXIII after
// Pentecost, in their own numeric order, right before the fixed final
// Sunday of the year (always Sunday XXIV's own formulary, regardless of
// how many Sundays actually elapsed since Pentecost). Ported directly
// from the reference engine's own `getweek()`
// (DivinumOfficium/Date.pm) — same rubric, same arithmetic (weeks-until-
// Advent, not a separately-tracked count of skipped Epiphany Sundays);
// confirmed against that source rather than re-derived by hand.
import { resolveSeason, sundayOnOrBefore, firstSundayStrictlyAfter, adventStart, easterOffsetOf } from './temporal'; import { resolveSeason, sundayOnOrBefore, firstSundayStrictlyAfter, adventStart, easterOffsetOf } from './temporal';
import { daysBetween } from './date-math'; import { daysBetween } from './date-math';
@@ -43,12 +50,29 @@ const EASTER_OFFSET_IDS: [number, string][] = [
[42, 'sunday-after-ascension'], [42, 'sunday-after-ascension'],
[49, 'pentecost-sunday'], [49, 'pentecost-sunday'],
]; ];
for (let n = 1; n <= 24; n++) { // Sundays I-XXII after Pentecost only — XXIII and XXIV are handled by
// resolvePostPentecost23Plus below, since (unlike I-XXII) which id a given
// week gets can depend on distance-to-Advent, not just its own offset.
for (let n = 1; n <= 22; n++) {
EASTER_OFFSET_IDS.push([56 + 7 * (n - 1), `post-pentecost-${String(n).padStart(2, '0')}`]); EASTER_OFFSET_IDS.push([56 + 7 * (n - 1), `post-pentecost-${String(n).padStart(2, '0')}`]);
} }
const EASTER_OFFSET_ID_MAP = new Map(EASTER_OFFSET_IDS); const EASTER_OFFSET_ID_MAP = new Map(EASTER_OFFSET_IDS);
const MAX_EASTER_OFFSET = EASTER_OFFSET_IDS[EASTER_OFFSET_IDS.length - 1]![0];
const MAX_EASTER_OFFSET_ID = EASTER_OFFSET_IDS[EASTER_OFFSET_IDS.length - 1]![1]; /**
* A governing Sunday at or beyond Pentecost week XXIII. `pentecostWeek` is
* the reference engine's own `$n` (1 = Trinity Sunday, verified against
* DivinumOfficium/Date.pm and its Tempora/PentNN file naming).
*/
function resolvePostPentecost23Plus(governingSunday: string, year: number, pentecostWeek: number): string {
const wdist = Math.floor((daysBetween(governingSunday, adventStart(year)) + 6) / 7);
if (wdist < 2) {
return 'post-pentecost-24';
}
if (pentecostWeek === 23) {
return 'post-pentecost-23';
}
return `post-epiphany-${8 - wdist}`;
}
export function resolveTemporalId(isoDate: string): string { export function resolveTemporalId(isoDate: string): string {
const season = resolveSeason(isoDate); const season = resolveSeason(isoDate);
@@ -78,9 +102,11 @@ export function resolveTemporalId(isoDate: string): string {
// regardless of which `season` bucket the feria itself falls in (the // regardless of which `season` bucket the feria itself falls in (the
// ferias right after Ash Wednesday genuinely reuse Quinquagesima's // ferias right after Ash Wednesday genuinely reuse Quinquagesima's
// collect, crossing what resolveSeason calls two different seasons). // collect, crossing what resolveSeason calls two different seasons).
const offset = easterOffsetOf(sundayOnOrBefore(isoDate)); const governingSunday = sundayOnOrBefore(isoDate);
if (offset > MAX_EASTER_OFFSET) { const offset = easterOffsetOf(governingSunday);
return MAX_EASTER_OFFSET_ID; const pentecostWeek = Math.round((offset - 49) / 7);
if (pentecostWeek >= 23) {
return resolvePostPentecost23Plus(governingSunday, year, pentecostWeek);
} }
return EASTER_OFFSET_ID_MAP.get(offset) ?? 'septuagesima'; return EASTER_OFFSET_ID_MAP.get(offset) ?? 'septuagesima';
} }
+23
View File
@@ -44,6 +44,29 @@ describe('getDayLabel — ordinal temporal label', () => {
}); });
}); });
describe('getDayLabel — resumed post-Epiphany Sunday (overflow years)', () => {
it('labels a resumed Sunday/weekday as "after Epiphany", not the next Trinity-counted number', () => {
// 2026: post-epiphany-5 is Nov 8, post-epiphany-6 is Nov 15 (both
// Sundays) -- see calendar/temporal-id.test.ts for the id-level
// coverage this label check builds on.
expect(getDayLabel(resolveDay('2026-11-08'))).toBe('The 5th Sunday after Epiphany');
expect(getDayLabel(resolveDay('2026-11-09'))).toBe('Monday in the 5th week after Epiphany');
expect(getDayLabel(resolveDay('2026-11-15'))).toBe('The 6th Sunday after Epiphany');
expect(getDayLabel(resolveDay('2026-11-16'))).toBe('Monday in the 6th week after Epiphany');
});
it('the fixed final Sunday of the year always shows the fixed 23rd-after-Trinity ordinal, not a raw elapsed-week count', () => {
// 2026-11-22 is the fixed post-pentecost-24 Sunday (Sunday XXIV after
// Pentecost's own fixed formulary; this app's Trinity-counted display
// is one week off from that Pentecost-counted id, so XXIV - 1 = 23).
// Every year 1900-2100 lands on this same id for its own last Sunday
// before Advent, so this ordinal is fixed, not overflow-year-specific
// -- confirmed against a non-overflow year (1943) too.
expect(getDayLabel(resolveDay('2026-11-22'))).toBe('The 23rd Sunday after Trinity');
expect(getDayLabel(resolveDay('1943-11-21'))).toBe('The 23rd Sunday after Trinity');
});
});
describe('getDayLabel — active octave', () => { describe('getDayLabel — active octave', () => {
it('shows the octave day itself as the primary label, plus a lesser saint commemorated alongside it', () => { it('shows the octave day itself as the primary label, plus a lesser saint commemorated alongside it', () => {
// St. Lawrence's own octave (Aug 10-17); Aug 12 is day 3, and also St. // St. Lawrence's own octave (Aug 10-17); Aug 12 is day 3, and also St.
+40
View File
@@ -0,0 +1,40 @@
import { describe, expect, it } from 'vitest';
import { resolveTemporalId } from '../../src/calendar/temporal-id';
import { resolveDay } from '../../src/calendar';
describe('resolveTemporalId — post-Pentecost overflow', () => {
// 2026: Easter 2026-04-05 -> only post-epiphany-1..5 occur before
// Septuagesima, so post-pentecost-24 through 27 (5 real weeks between
// XXIII and the last Sunday) resume as Epiphany V and VI before landing
// on the fixed final Sunday. Confirmed against the reference engine's
// own DivinumOfficium/Date.pm getweek() (Pent/Epi arithmetic), not just
// hand-derived.
it('resumes the skipped post-Epiphany Sundays in order before the fixed last Sunday', () => {
expect(resolveTemporalId('2026-11-07')).toBe('post-pentecost-23');
expect(resolveTemporalId('2026-11-14')).toBe('post-epiphany-5');
expect(resolveTemporalId('2026-11-21')).toBe('post-epiphany-6');
expect(resolveTemporalId('2026-11-28')).toBe('post-pentecost-24');
});
it('does not resume anything in a non-overflow year (all 6 post-Epiphany Sundays occurred)', () => {
// 1943: Easter 1943-04-25, latest possible-ish Easter -> all 6
// post-Epiphany Sundays occur, so post-pentecost climbs past 24
// without ever touching Epiphany content, capping at the fixed id.
expect(resolveTemporalId('1943-11-21')).toBe('post-pentecost-24');
});
});
describe('post-Epiphany VI commemoration on the Saturday before Septuagesima', () => {
it('fires only when Epiphany V was the last Sunday to occur (2022, 2025)', () => {
const day2022 = resolveDay('2022-02-12');
expect(day2022.commemorations).toContainEqual({ kind: 'temporal', id: 'post-epiphany-6' });
const day2025 = resolveDay('2025-02-15');
expect(day2025.commemorations).toContainEqual({ kind: 'temporal', id: 'post-epiphany-6' });
});
it('does not fire when all 6 post-Epiphany Sundays occurred (1943)', () => {
const day = resolveDay('1943-02-20');
expect(day.commemorations).not.toContainEqual({ kind: 'temporal', id: 'post-epiphany-6' });
});
});