diff options
Diffstat (limited to 'lib/rites/rite_ef')
| -rw-r--r-- | lib/rites/rite_ef/temporal_ef.ml | 122 | ||||
| -rw-r--r-- | lib/rites/rite_ef/temporal_ef.mli | 11 |
2 files changed, 131 insertions, 2 deletions
diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml index 1ce9de9..721790d 100644 --- a/lib/rites/rite_ef/temporal_ef.ml +++ b/lib/rites/rite_ef/temporal_ef.ml @@ -104,6 +104,56 @@ let christ_the_king y = sunday_on_or_before (mk y 10 31) 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 +(* RG 17(a) (Caput III, "De Dominicis"; full text on [holy_family_sunday]'s + own citation above): "festum Ss.mi Nominis Iesu, celebrandum dominica quae + occurrit a die 2 ad 5 ianuarii (secus die 2 ianuarii)" -- the feast of the + Most Holy Name of Jesus, celebrated on the Sunday falling 2-5 January, + OTHERWISE [on] 2 January [itself]. [None] here means no such Sunday exists + that year -- [holy_name_fallback_date]'s own fallback branch is for + exactly that case; see its own citation for why the window CAN be empty + (unlike (b)'s 7-13 January window, which never is). + + Formula: the Sunday on or before 5 January is in [2,5] iff it is not + before 2 January -- the window is only 4 days wide, so there is at most + one Sunday in it either way. *) +let holy_name_sunday y = + let s = sunday_on_or_before (mk y 1 5) in + if on_or_after s (mk y 1 2) then Some s else None + +(* RG 17(a)'s own "secus die 2 ianuarii" clause, and the calendarium's + January table, BOTH photographic scans, word for word (docs/research/ + rules-register.md; also confirmed in the Mass propers' own heading for + this feast, both scans, Caput "Sanctissimi Nominis Iesu": "DOMINICA a die + 2 ad diem 5 ianuarii occurrenti, VEL, SI HAEC DEFECERIT, DIE 2 IANUARII" -- + the SUNDAY occurring 2-5 January, OR, IF THIS IS LACKING, [on] 2 January): + *"Dominica inter octavam Nativitatis Domini et Epiphaniam, vel, EA + DEFICIENTE, die 2 ianuarii: Sanctissimi Nominis Iesu, II classis"* -- the + Sunday between the Octave of the Nativity and Epiphany, or, THAT FAILING, + 2 January. Unlike [holy_family_sunday]'s 7-13 January window (which can + never be empty of a Sunday), this 2-5 January window CAN be, and is in + 3,619 of the 8,417 years in [1583, 9999] (a plain weekday check, + independently cross-checked against `date -d`) -- [temporal]'s own + dispatch applies this fallback date, tagged exactly like the Sunday shape + (subject Lord, the same Latin name), only when [holy_name_sunday y] is + [None] for that date's own civil year. *) +let holy_name_fallback_date y = mk y 1 2 + +(* The ONE Latin title both of RG 17(a)'s two shapes (the Sunday and the 2 + January fallback) carry -- ONE feast, RG 91's own "primum mobilia, deinde + fixa" language notwithstanding (see [temporal]'s own fallback-branch + comment for why both shapes band identically at entry 14's MOVABLE half, + not split across the two halves by year). Bound once so the two [temporal] + branches that use it cannot silently drift apart, the same discipline + [holy_family_sunday] already gets from being named instead of re-derived. + Both photographic scans, word for word, twice over (the calendarium's own + January table AND the Mass propers' own running header/heading, this + file's own citations on [holy_name_sunday]/[holy_name_fallback_date] + above): "Sanctissimi Nominis Iesu". No English name, deliberately -- the + SAME "would read the oracle it is compared against" reasoning + [holy_family_sunday]'s own [names] comment below gives for Holy Family. *) +let holy_name_names = + Colitur_kernel.Names.of_list [ (Colitur_kernel.Lang.of_string_exn "la", "Sanctissimi Nominis Iesu") ] + 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), @@ -533,15 +583,68 @@ let temporal d = item on Holy Name of Jesus, RG 17(a)) -- this is a targeted addition for the one day this task built, not a claim that the gap is closed generally. *) + (* RG 17(a) (this file's own [holy_name_sunday], full citation + there): the SECOND Sunday a year this branch must not + leave [subject = Temporal] -- added alongside Holy + Family's own check above, not replacing it (the two + windows, 2-5 and 7-13 January, never overlap, so at most + one of the two conditions is ever true for a given [d]). + Guarded on [holy_name_sunday y = Some d] rather than only + "is [d] in [2,5] January": every OTHER Sunday in that + range must stay unnamed, and in a year where a DIFFERENT + day of the window is the one true Sunday, [d] itself is + never reached by [sunday_slug] as a Sunday to begin with + (weekday alone already excludes it) -- but writing the + check this way, against the SAME independently-computed + date [holy_name_sunday] returns rather than a bare month/ + day range, is what test_temporal_ef.ml's own anchor test + below cross-checks against. *) let subject, names = if same d (holy_family_sunday y) then ( Colitur_kernel.Subject.Lord, Colitur_kernel.Names.of_list [ (Colitur_kernel.Lang.of_string_exn "la", "Sanctae Familiae Iesu, Mariae, Ioseph") ] ) + else if holy_name_sunday y = Some d then (Colitur_kernel.Subject.Lord, holy_name_names) else (Colitur_kernel.Subject.Temporal, Colitur_kernel.Names.empty) in build ~subject ~names ~season:s ~slug ~colour ~rank ~week:(week d) () - | None -> ( + | None -> + (* RG 17(a)'s own fallback, "secus die 2 ianuarii" (full + citation on [holy_name_fallback_date] above): ONLY when + [holy_name_sunday y] is [None] for [d]'s own civil year -- + i.e. 2-5 January genuinely has no Sunday that year -- does + 2 January itself carry the feast; every other year, 2 + January is an ordinary Christmastide feria, exactly what + [christmastide_feria_slug] below already computes for it. + Checked here, ahead of that generic fallback, the same way + [named]'s own fixed dates are checked ahead of everything + ferial -- NOT folded into [named] itself, because unlike + every one of [named]'s ~20 entries this one is + CONDITIONAL on a per-year fact ([holy_name_sunday y] = + [None]) that [named]'s bare [Date.t -> ... option] shape + has no way to express without threading [subject] through + every one of its other branches too -- the same reason + Holy Family, immediately above, is not one of [named]'s + outputs either (that branch's own comment). + + Season Christmastide (RG 72-73: 2 January is always within + it); rank/colour/subject/names identical to the Sunday + shape immediately above -- ONE feast, {!holy_name_names}'s + own comment on why both shapes share it. Band-classified + at entry 14's MOVABLE half regardless of which shape fired + this year (Precedence_ef.band; both shapes are built + through this same [temporal] function, hence [origin = + Temporal] either way) -- RG 91's "primum mobilia, deinde + fixa" split is a property of the TABLE ENTRY a feast + occupies, and RG 17(a) names ONE feast with a fallback + clause, not two differently-classified feasts that happen + to share a Mass formulary; the Mass propers' own heading + (docs/research/rules-register.md) states both shapes under + the identical title for exactly this reason. *) + if same d (holy_name_fallback_date y) && holy_name_sunday y = None then + build ~subject:Colitur_kernel.Subject.Lord ~names:holy_name_names ~season:Christmastide + ~slug:"ef-holy-name" ~colour:Colour.White ~rank:Class2 ~week:(week d) () + else ( match christmastide_feria_slug d with | Some slug -> build ~season:s ~slug ~colour:(season_colour s) ~rank:(ferial_rank d s) @@ -608,7 +711,19 @@ let temporal d = 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. *) + this guard catching it, same as any other entry here. + + Holy Name of Jesus (RG 17(a)) is the SAME shape, restated per-year rather + than as a single fixed pair: exactly ONE of its two slugs exists for any + given [y] ([holy_name_sunday y] is [Some] xor [None]), so exactly one + entry -- "ef-holy-name-sunday" at that Sunday, or "ef-holy-name" at + [holy_name_fallback_date y] -- is appended below, matching whichever + shape [temporal] itself will actually build that year. An erosion of + EITHER branch is still caught: {!Validate.run} calls [anchors] for both + the civil year a date falls in and the one before it (a liturgical year + straddles two), so across any two consecutive years both shapes are + exercised regardless of which one civil year [y] itself happens to + land on. *) let anchors y = let easter = Computus.gregorian_easter y in let off n = Date.add_days easter n in @@ -633,6 +748,9 @@ let anchors y = ("ef-corpus-christi", off 60); ("ef-sacred-heart", off 68); ("ef-christ-the-king", christ_the_king y) ] + @ (match holy_name_sunday y with + | Some d -> [ ("ef-holy-name-sunday", d) ] + | None -> [ ("ef-holy-name", holy_name_fallback_date y) ]) (* Compile-time check that this module satisfies the kernel's rite contract. *) module _ : Colitur_kernel.Temporal.RITE = struct diff --git a/lib/rites/rite_ef/temporal_ef.mli b/lib/rites/rite_ef/temporal_ef.mli index 68fe64e..5e85111 100644 --- a/lib/rites/rite_ef/temporal_ef.mli +++ b/lib/rites/rite_ef/temporal_ef.mli @@ -21,6 +21,17 @@ val christ_the_king : int -> Date.t fallback for it), so this needs none. *) val holy_family_sunday : int -> Date.t +(** RG 17(a): the Sunday falling 2-5 January in civil year [y], the Most Holy + Name of Jesus's own primary date -- [None] when no such Sunday exists + that year (3,619 of the 8,417 years in [1583, 9999]), unlike + {!holy_family_sunday}'s window, which never is. *) +val holy_name_sunday : int -> Date.t option + +(** RG 17(a)'s own "secus die 2 ianuarii" fallback: 2 January in civil year + [y]. Only actually carries the feast when {!holy_name_sunday} [y] is + [None] for that year -- {!temporal} is what applies that condition. *) +val holy_name_fallback_date : int -> Date.t + (** The named temporal days: I-class feasts of the Lord, vigils, and days within the Octave of the Nativity. Returns (season, slug, colour, rank). Carries no week of its own -- {!temporal} computes it uniformly via {!week} for |
