aboutsummaryrefslogtreecommitdiff
path: root/internal/calendar/precedence_ef_repro_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-18 17:33:20 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-18 17:33:20 +0200
commite713da2d796eabc55d407ad2f8488861e7598798 (patch)
tree792d9911af15e2f875046cfcbb09b8a6e015dde3 /internal/calendar/precedence_ef_repro_test.go
parentd27336dc65c7348dcda639b7e43e8948e7bb1caa (diff)
downloadlectio-e713da2d796eabc55d407ad2f8488861e7598798.tar.gz
lectio-e713da2d796eabc55d407ad2f8488861e7598798.zip
fix(ef): two I-class feasts can no longer transfer onto the same day
RG 97/98 require a year's impeded I-class transfers to be resolved together. transferIfImpededEF resolved each one independently, so when an early Easter impedes both St Joseph (19 March) and the Annunciation (25 March), both walked to the Monday after Low Sunday -- and St Joseph, losing pickEF there, was observed on NO day of 2008, 2035 or 2046 at all. He appeared only as a commemoration in the Annunciation's tail. RG 96(a) settles it outright, and it is not a tie-break: the Annunciation transferred after Easter has a sedes propria -- "quando est transferendum post Pascha, transfertur, tamquam in sedem propriam, in feriam II post dominicam in albis". It claims the Monday by law; the rest queue in RG 98's order (table position, then the office impeded first) and walk around it. New efTransferPlan resolves the whole year's transfers as a set and hands each feast its target; transferIfImpededEF keeps the single-candidate walk and All Souls. The stale doc comment recording this as a known unfixable limitation is replaced -- its reasoning argued RG 97/98 tie-breaks, when RG 96(a) decides the only collision the universal calendar actually produces. 2008-04-01, 2035-04-03, 2046-04-03 ef-easter-2-tuesday -> St Joseph Matches colitur on all three. Mutation-tested: bypassing the plan reddens the new test on all three years. fix(ef): 13 January's Baptism is omitted when Holy Family falls on it The Holy Family Mass propers, verbatim in both photographic scans of the 1962 Missal: "Si festum S. Familiae occurrerit die 13 ianuarii, Missa dicitur de festo S. Familiae, sine commemoratione Baptismatis D.N.I.C., et sine commemoratione dominicae." Sine commemoratione: the Baptism is omitted outright, not merely outranked, so the candidate is dropped rather than left in Others. Structurally the same answer RG 91 entry 14 gives (Festa Domini II classis: primum mobilia, deinde fixa), but the propers' rubric is the direct authority for the omission. lectio kept the Baptism as the observed office on all seven such years in 2005-2050 -- 2008, 2013, 2019, 2030, 2036, 2041, 2047 -- and never observed the Holy Family Mass on 13 January at all. It already had the Holy Family Mass on every other Sunday after Epiphany, so this was the one date it could not reach. 13 rows of the 16801-day differential fixture change; colitur agrees with all of them.
Diffstat (limited to 'internal/calendar/precedence_ef_repro_test.go')
-rw-r--r--internal/calendar/precedence_ef_repro_test.go58
1 files changed, 58 insertions, 0 deletions
diff --git a/internal/calendar/precedence_ef_repro_test.go b/internal/calendar/precedence_ef_repro_test.go
index 11fd6ca..1408c7c 100644
--- a/internal/calendar/precedence_ef_repro_test.go
+++ b/internal/calendar/precedence_ef_repro_test.go
@@ -11,6 +11,7 @@ package calendar_test
// covered separately, package-internal, in precedence_ef_test.go).
import (
+ "strings"
"testing"
"time"
@@ -158,3 +159,60 @@ func TestPurificationBeatsFebruarySunday(t *testing.T) {
}
}
}
+
+// TestEFTwoTransfersDoNotCollide: RG 97/98 -- when an early Easter impedes BOTH
+// St Joseph (19 March) and the Annunciation (25 March), each must land on a day
+// of its own. Resolving the two walks independently sent both to the Monday
+// after Low Sunday, where St Joseph lost pickEF and was observed on NO day of
+// 2008, 2035 or 2046 at all.
+//
+// RG 96(a) fixes the Annunciation's target outright -- "quando est transferendum
+// post Pascha, transfertur, tamquam in sedem propriam, in feriam II post
+// dominicam in albis" -- so it is not a tie-break: the Annunciation takes the
+// Monday by law and St Joseph walks to the Tuesday.
+func TestEFTwoTransfersDoNotCollide(t *testing.T) {
+ for _, c := range []struct{ annunciation, joseph string }{
+ {"2008-03-31", "2008-04-01"},
+ {"2035-04-02", "2035-04-03"},
+ {"2046-04-02", "2046-04-03"},
+ } {
+ for _, w := range []struct{ date, want string }{
+ {c.annunciation, "annunciation-of-the-blessed-virgin-mary"},
+ {c.joseph, "joseph-spouse-of-the-bl-virgin-mary"},
+ } {
+ got := efCompute(w.date).Observed.Slug
+ if got != w.want {
+ t.Errorf("%s observed = %q, want %q", w.date, got, w.want)
+ }
+ }
+ }
+}
+
+// TestEFBaptismOmittedOnHolyFamilySunday: the Holy Family Mass propers, verbatim
+// in both photographic scans of the 1962 Missal -- "Si festum S. Familiae
+// occurrerit die 13 ianuarii, Missa dicitur de festo S. Familiae, sine
+// commemoratione Baptismatis D.N.I.C., et sine commemoratione dominicae."
+//
+// So on a 13 January that is itself the Sunday after Epiphany the day is the
+// Holy Family (Col 3:12-17 / Luke 2:42-52) and the Baptism is omitted OUTRIGHT,
+// not commemorated -- Others must be empty of it. lectio previously kept the
+// Baptism as the observed office on both such years in 2005-2050.
+func TestEFBaptismOmittedOnHolyFamilySunday(t *testing.T) {
+ for _, y := range []string{"2008", "2013", "2019", "2030", "2036", "2041", "2047"} {
+ d := efCompute(y + "-01-13")
+ if d.Observed.Slug != "ef-time-after-epiphany-sunday-1" {
+ t.Errorf("%s-01-13 observed = %q, want ef-time-after-epiphany-sunday-1 (Holy Family)", y, d.Observed.Slug)
+ }
+ for _, o := range d.Others {
+ if strings.Contains(o.Slug, "baptism") {
+ t.Errorf("%s-01-13 commemorates %q; the rubric says sine commemoratione Baptismatis", y, o.Slug)
+ }
+ }
+ }
+ // A 13 January that is NOT the Sunday after Epiphany keeps the Baptism.
+ for _, y := range []string{"2026", "2035"} {
+ if got := efCompute(y + "-01-13").Observed.Slug; got != "commemoration-of-the-baptism-of-the-lord" {
+ t.Errorf("%s-01-13 observed = %q, want commemoration-of-the-baptism-of-the-lord", y, got)
+ }
+ }
+}