From bbc8ce26916ca92b3c2286c57342a6565323b66f Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 08:11:26 +0200 Subject: temporal(ef): the Holy Family, first Sunday after Epiphany (RG 17(b)) RG 17(b), verified against both photographic scans (missale-romanum- 1962.pdf and "Missale Romanum 1962_text.pdf" -- the electronic transcription carries the same paragraph, so this one is not itself a transcription-vs-scan divergence): the Holy Family of Jesus, Mary and Joseph is celebrated on the first Sunday after Epiphany, II class, EVERY year, taking the Sunday's own place "cum omnibus iuribus et privilegiis" -- the same formula RG 16(a) already uses. The slug, rank and colour temporal_ef.ml already computed for that Sunday (ef-time-after-epiphany-sunday-1, Class2, white) turn out to be exactly right by coincidence -- an ordinary, unnamed Sunday and Holy Family share both. The only field that was silently wrong is subject: always Temporal before this, when RG 91 entry 14 ("Festa Domini II classis, primum mobilia, deinde fixa") calls Holy Family a movable Feast of the Lord. temporal's build now takes an optional ~subject, applied only on Holy Family's own date -- every other Sunday, including the still-unbuilt Holy Name of Jesus (RG 17(a)), is unaffected. RG 17(b)'s window (7-13 January) can never be empty of a Sunday -- sunday_on_or_before(6 Jan) + 7 always lands in [7, 13] regardless of 6 January's weekday -- unlike RG 17(a)'s Holy Name (2-5 January, CAN be empty), whose calendarium entry carries an explicit "vel ea deficiente, die 2 ianuarii" fallback right next to Holy Family's own, fallback-free one. No fallback needed or built. Added to anchors (holy_family_sunday is independently computed, not routed through named -- see temporal_ef.ml's own comment on why) and to its own dedicated anchor/erosion test in test_temporal_ef.ml, kept separate from the generic named-days coverage test since this genuinely isn't one of named's own outputs. Does not yet touch precedence: band still has no notion of a movable Class2 Lord feast (entry 14 gates on sanctoral origin only), so on the seven years 13 January is itself Holy Family's date (2008, 2013, 2019, 2030, 2036, 2041, 2047), the fixed Commemoration of the Baptism of the Lord still wins the day exactly as before this commit -- the next commit fixes the ordering RG 91 entry 14's own text states ("primum mobilia, deinde fixa"). --- lib/rites/rite_ef/temporal_ef.ml | 89 +++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 11 deletions(-) (limited to 'lib/rites/rite_ef/temporal_ef.ml') diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml index 7782876..0647aac 100644 --- a/lib/rites/rite_ef/temporal_ef.ml +++ b/lib/rites/rite_ef/temporal_ef.ml @@ -64,6 +64,46 @@ let season d = citation gap. *) let christ_the_king y = sunday_on_or_before (mk y 10 31) +(* RG 17(b) (Caput III, "De Dominicis"), primary text, verified against BOTH + photographic scans (missale-romanum-1962.pdf and "Missale Romanum + 1962_text.pdf" -- the electronic transcription, 1962-06-23,_SS_Ioannes + _XXIII,_Missale_Romanum,_LT.pdf, carries the SAME text here, so this one + paragraph is not itself a transcription-vs-scan divergence): "17. + Dominica excludit, per se, assignationem perpetuam festorum. Excipiuntur: + a) festum Ssmi Nominis Iesu, celebrandum dominica quae occurrit a die 2 + ad 5 ianuarii (secus die 2 ianuarii); b) festum S. Familiae Iesu, Mariae, + Ioseph, celebrandum dominica prima post Epiphaniam; ... Haec festa locum + tenent dominicae occurrentis cum omnibus iuribus et privilegiis: de + dominica, proinde, nulla fit commemoratio" -- a Sunday of itself excludes + the perpetual assignment of feasts to it; EXCEPTED: (a) the Most Holy + Name of Jesus, celebrated on the Sunday falling 2-5 January (otherwise 2 + January); (b) the HOLY FAMILY of Jesus, Mary and Joseph, celebrated on + the FIRST SUNDAY AFTER EPIPHANY; ... these feasts hold the place of the + occurring Sunday with ALL its rights and privileges: of the Sunday, + therefore, NO commemoration is made -- the identical "cum omnibus + iuribus et privilegiis: nulla fit commemoratio" formula RG 16(a) already + uses for a FIXED-date Lord feast impeding a Sunday (register §6.0), + stated here for the Sunday-ASSIGNED feasts RG 17 itself lists by letter. + + UNLIKE (a)'s own narrow 2-5 January window (which CAN be empty of a + Sunday -- the calendarium's own January table carries an explicit "vel ea + deficiente, die 2 ianuarii" fallback for it, scan-verified), (b)'s 7-13 + January window can NEVER be empty: [sunday_on_or_before (mk y 1 6)] is, + by construction, at most 6 days before 6 January, so adding 7 always + lands in [7, 13] regardless of which weekday 6 January falls on (every + one of the 7 possible cases is exercised by test_temporal_ef.ml's own + [test_holy_family]). The calendarium's own text for (b), both in RG 17 + itself and in its January table entry ("Dominica I post Epiphaniam: + S. Familiae, Iesu, Mariae, Ioseph, II classis"), carries no fallback + clause of any kind -- consistent with there being no gap for one to + cover. + + Formula IDENTICAL to [week_origin]'s own [Time_after_epiphany] case below + (the first Sunday after Epiphany) -- not re-derived a second time, just + named here for its own citation and so [temporal] can test a specific + date against it without reaching into [week_origin]'s implementation. *) +let holy_family_sunday y = Date.add_days (sunday_on_or_before (mk y 1 6)) 7 + let same a b = Date.compare a b = 0 (* Named temporal days: the I-class feasts of the Lord (RG 91 entries 1 and 3), @@ -404,15 +444,15 @@ let temporal d = let easter = Computus.gregorian_easter y in let s = season d in let weekday = Date.weekday d in - let build ~season ~slug ~colour ~rank ~week = + let build ?(subject = Colitur_kernel.Subject.Temporal) ~season ~slug ~colour ~rank ~week () = let office = - Colitur_kernel.Celebration.make ~slug:(Slug.of_string_exn slug) ~rank ~colour - ~subject:Colitur_kernel.Subject.Temporal ~layer:"temporal" () + Colitur_kernel.Celebration.make ~slug:(Slug.of_string_exn slug) ~rank ~colour ~subject + ~layer:"temporal" () in { Colitur_kernel.Temporal.season; week; weekday; office } in match named d with - | Some (season, slug, colour, rank) -> build ~season ~slug ~colour ~rank ~week:(week d) + | Some (season, slug, colour, rank) -> build ~season ~slug ~colour ~rank ~week:(week d) () | None -> ( (* Rogations (the Minor Litanies only -- RG 87, Monday and Tuesday before Ascension). The Major Litanies (25 April, RG 80) are a fixed @@ -441,10 +481,10 @@ let temporal d = if rogation = 36 || rogation = 37 then build ~season:s ~slug:(if rogation = 36 then "ef-rogation-monday" else "ef-rogation-tuesday") - ~colour:Colour.Violet ~rank:(ferial_rank d s) ~week:(week d) + ~colour:Colour.Violet ~rank:(ferial_rank d s) ~week:(week d) () else match ember d with - | Some (slug, rank, colour) -> build ~season:s ~slug ~colour ~rank ~week:(week d) + | Some (slug, rank, colour) -> build ~season:s ~slug ~colour ~rank ~week:(week d) () | None -> ( match sunday_slug d with | Some slug -> @@ -456,11 +496,29 @@ let temporal d = reaches this fallback -- leaving II class here except the remaining Advent and Lent Sundays. *) let rank = match s with Advent | Lent -> Class1 | _ -> Class2 in - build ~season:s ~slug ~colour ~rank ~week:(week d) + (* RG 17(b) (this file's own [holy_family_sunday], full + citation there): the ONE Sunday a year this branch must + NOT leave [subject = Temporal] (this function's own + default) -- the Holy Family, whose slug/rank/colour are + otherwise EXACTLY what this branch already computes for + the 7-13 January Sunday (an accident this task's own + oracle-strengthening work exposed: rank/colour alone + could never distinguish "Holy Family" from "an ordinary, + unnamed Sunday", since they happen to coincide). Every + OTHER Sunday this branch ever builds -- including the + narrower Holy Name of Jesus window, RG 17(a), still + unbuilt as its own named day, register §6 -- keeps + [Temporal], unaffected. *) + let subject = + if same d (holy_family_sunday y) then Colitur_kernel.Subject.Lord + else Colitur_kernel.Subject.Temporal + in + build ~subject ~season:s ~slug ~colour ~rank ~week:(week d) () | None -> ( match christmastide_feria_slug d with | Some slug -> - build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s) ~week:(week d) + build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s) + ~week:(week d) () | None -> (* The days between Ash Wednesday and Lent I have proper Masses and belong to no numbered week. *) @@ -468,7 +526,7 @@ let temporal d = if after_ashes >= -45 && after_ashes <= -43 then build ~season:s ~slug:(Printf.sprintf "ef-lent-after-ashes-%s" (weekday_word d)) - ~colour:Colour.Violet ~rank:Class3 ~week:None + ~colour:Colour.Violet ~rank:Class3 ~week:None () else let colour = (* The Pentecost octave weekdays are red, not Paschaltide's white. *) @@ -508,14 +566,22 @@ let temporal d = Printf.sprintf "ef-%s-%d-%s" (season_slug_word s) (Option.value week_n ~default:0) (weekday_word d) in - build ~season:s ~slug ~colour ~rank:(ferial_rank d s) ~week:week_n))) + build ~season:s ~slug ~colour ~rank:(ferial_rank d s) ~week:week_n ()))) (* Independent restatement of [named]'s fixed and Easter-relative dates, paired with the slug each should carry, for civil year [y]. Deliberately NOT derived from [named] itself -- consumed by [Validate]'s anchor- agreement check (design spec §5.7), which exists precisely to catch an accidental single-site drift (e.g. Ascension's [off 39] silently becoming - [off 40]) that both sides moving together would hide. *) + [off 40]) that both sides moving together would hide. + + [holy_family_sunday] is NOT one of [named]'s own outputs (its own + citation above explains why -- [temporal] applies it as a targeted + [subject] override inside [sunday_slug]'s branch, not through [named]'s + 4-tuple), but it is exactly the same kind of independently-computed + anchor this list exists to guard -- an accidental drift in + [holy_family_sunday]'s own [+7] would silently move Holy Family without + this guard catching it, same as any other entry here. *) let anchors y = let easter = Computus.gregorian_easter y in let off n = Date.add_days easter n in @@ -526,6 +592,7 @@ let anchors y = ("ef-nativity-octave-day-7", mk y 12 31); ("ef-circumcision", mk y 1 1); ("ef-epiphany", mk y 1 6); + ("ef-time-after-epiphany-sunday-1", holy_family_sunday y); ("ef-ash-wednesday", off (-46)); ("ef-passion-sunday", off (-14)); ("ef-palm-sunday", off (-7)); -- cgit v1.3