aboutsummaryrefslogtreecommitdiff
path: root/internal/calendar/temporal_ef_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-12 17:15:03 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-12 17:15:03 +0200
commit3b32c002d3eddda5ece9422442717657b9fee63b (patch)
tree5dd82811c100de6daa995bebd115a12434296508 /internal/calendar/temporal_ef_test.go
parent2386a4551aec94252168a8554269ee423d516882 (diff)
parentc655c525ef07deafb113a291489b396c81d7ce4a (diff)
downloadlectio-3b32c002d3eddda5ece9422442717657b9fee63b.tar.gz
lectio-3b32c002d3eddda5ece9422442717657b9fee63b.zip
Merge branch 'fix/ef-precedence-defects': seven EF calendar defects
Fixes seven defects in the EF calendar, each found by differential and oracle comparison against an independently-written engine and each backed by a cited paragraph of the Rubricae Generales verified against the 1962 Missal: RG 96 transfers must skip II-class days (the Precious Blood was landing on the Visitation) RG 91 a II-class privileged feria yields to an equal-class feast (St Matthew was losing to the September Ember Wednesday) RG 11 all Sundays of Advent, Lent and Passiontide are I class (only Advent I was), which also settles St Joseph on a Lent Sunday RG 131 Rose on Gaudete and Laetare, which the EF path never emitted RG 122 Holy Thursday is white and the sanctoral generator itself, whose rank inference had tagged 15 III-class feasts as commemorations, dropped four entries to slug collisions, and mis-tagged three class fields. The EF oracle test asserted Season only, which is why none of this ever failed. It now asserts rank and colour, with a cited allow-list. Two commemorations had been deleted on a primary-source claim the primary source contradicts: the Archivum Liturgicum transcription silently drops commemoration lines where the photographic scans carry them. Six of the seven affected dates are now present; the seventh (25 December) is blocked by an ingestion limit that reads only the first of three Christmas Masses, recorded at its cause. Known gap, recorded in source: RG 95/97/98 chained transfers, where two I-class feasts translate to the same day.
Diffstat (limited to 'internal/calendar/temporal_ef_test.go')
-rw-r--r--internal/calendar/temporal_ef_test.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/internal/calendar/temporal_ef_test.go b/internal/calendar/temporal_ef_test.go
index 6d632e2..8b1ffa5 100644
--- a/internal/calendar/temporal_ef_test.go
+++ b/internal/calendar/temporal_ef_test.go
@@ -38,3 +38,95 @@ func TestTemporalEFChristTheKing(t *testing.T) {
t.Errorf("efChristTheKing(2025) = %s want 2025-10-26", got)
}
}
+
+// TestTemporalEFSundayRanks: RG 11-12 / RG 91 entry 6 -- Sundays of Advent,
+// Lent and Passiontide, and Low Sunday, are I class; all others (including
+// Septuagesima's own three Sundays and the ordinary Sundays after Epiphany/
+// Pentecost) stay II class. Before the fix, only Advent I was I class; every
+// other Advent/Lent Sunday was left at the generic-Sunday II-class default.
+func TestTemporalEFSundayRanks(t *testing.T) {
+ cases := []struct {
+ date string
+ want Rank
+ }{
+ {"2025-11-30", RankClass1}, // Advent I
+ {"2025-12-07", RankClass1}, // Advent II
+ {"2025-12-14", RankClass1}, // Advent III (Gaudete)
+ {"2025-12-21", RankClass1}, // Advent IV
+ {"2025-03-09", RankClass1}, // Lent I
+ {"2025-03-16", RankClass1}, // Lent II
+ {"2025-03-23", RankClass1}, // Lent III
+ {"2025-03-30", RankClass1}, // Lent IV (Laetare)
+ {"2025-04-06", RankClass1}, // Passion Sunday
+ {"2025-04-13", RankClass1}, // Palm Sunday
+ {"2025-04-27", RankClass1}, // Low Sunday
+ {"2025-02-16", RankClass2}, // Septuagesima Sunday -- NOT I class
+ {"2025-02-23", RankClass2}, // Sexagesima Sunday -- NOT I class
+ {"2025-03-02", RankClass2}, // Quinquagesima Sunday -- NOT I class
+ {"2025-06-22", RankClass2}, // II Sunday after Pentecost -- ordinary II class
+ }
+ for _, c := range cases {
+ got := temporalEF(d(c.date))
+ if got.Cel.Rank != c.want {
+ t.Errorf("temporalEF(%s).Cel.Rank = %s, want %s (%s)", c.date, got.Cel.Rank, c.want, got.Cel.Slug)
+ }
+ }
+}
+
+// TestTemporalEFRoseSundays: RG 131 -- rose is permitted on Gaudete (Advent
+// III) and Laetare (Lent IV), for that Sunday's own Office and Mass only.
+// Before the fix, efColour had no Rose case at all.
+func TestTemporalEFRoseSundays(t *testing.T) {
+ if got := temporalEF(d("2025-12-14")).Cel.Colour; got != Rose {
+ t.Errorf("Gaudete (2025-12-14) colour = %s, want rose", got)
+ }
+ if got := temporalEF(d("2025-03-30")).Cel.Colour; got != Rose {
+ t.Errorf("Laetare (2025-03-30) colour = %s, want rose", got)
+ }
+ // The Advent/Lent Sundays either side stay violet -- rose is an indult for
+ // that one Sunday, not a season colour.
+ if got := temporalEF(d("2025-12-07")).Cel.Colour; got != Violet {
+ t.Errorf("Advent II (2025-12-07) colour = %s, want violet", got)
+ }
+ if got := temporalEF(d("2025-03-23")).Cel.Colour; got != Violet {
+ t.Errorf("Lent III (2025-03-23) colour = %s, want violet", got)
+ }
+}
+
+// TestTemporalEFHolyThursdayColour: RG 128(b)/RG 122 -- Holy Thursday's Mass
+// of Chrism and Mass in Cena Domini are white, a whole-day exception to
+// Passiontide's violet. Good Friday and Holy Saturday, either side, stay
+// violet (their own black/no-colour exceptions are a separate, unmodelled
+// gap -- see RG 132, precedence_ef.go's own doc comments).
+func TestTemporalEFHolyThursdayColour(t *testing.T) {
+ easter := d("2025-04-20")
+ holyThu := easter.AddDate(0, 0, -3)
+ goodFri := easter.AddDate(0, 0, -2)
+ holySat := easter.AddDate(0, 0, -1)
+ if got := temporalEF(holyThu).Cel.Colour; got != White {
+ t.Errorf("Holy Thursday colour = %s, want white", got)
+ }
+ if got := temporalEF(goodFri).Cel.Colour; got != Violet {
+ t.Errorf("Good Friday colour = %s, want violet (unchanged)", got)
+ }
+ if got := temporalEF(holySat).Cel.Colour; got != Violet {
+ t.Errorf("Holy Saturday colour = %s, want violet (unchanged)", got)
+ }
+}
+
+// TestTemporalEFEmberDayRanks: RG 91 entry 18 -- the Ember days of Lent (and,
+// unchanged, September and Advent) are II-class privileged ferias, not the
+// ordinary III-class Lenten ferias around them. Before the fix, efEmberSlug
+// had no Lent case at all, so Lent's Ember Wed/Fri/Sat fell through to the
+// ordinary III-class Lenten-feria rank.
+func TestTemporalEFEmberDayRanks(t *testing.T) {
+ // Lent I Sunday 2025 = 2025-03-09; Ember Wed/Fri/Sat = +3/+5/+6.
+ lentI := d("2025-03-09")
+ for _, off := range []int{3, 5, 6} {
+ day := lentI.AddDate(0, 0, off)
+ got := temporalEF(day)
+ if got.Cel.Rank != RankClass2 {
+ t.Errorf("Lent Ember day %s rank = %s, want class-2 (%s)", day.Format("2006-01-02"), got.Cel.Rank, got.Cel.Slug)
+ }
+ }
+}