aboutsummaryrefslogtreecommitdiff
path: root/lib/rites/rite_ef
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rites/rite_ef')
-rw-r--r--lib/rites/rite_ef/rite_ef.ml4
-rw-r--r--lib/rites/rite_ef/temporal_ef.ml62
-rw-r--r--lib/rites/rite_ef/temporal_ef.mli11
3 files changed, 77 insertions, 0 deletions
diff --git a/lib/rites/rite_ef/rite_ef.ml b/lib/rites/rite_ef/rite_ef.ml
index e48ff33..ba1274b 100644
--- a/lib/rites/rite_ef/rite_ef.ml
+++ b/lib/rites/rite_ef/rite_ef.ml
@@ -39,6 +39,10 @@ let context ~lectionary ~commons : (Vocab_ef.season, Vocab_ef.rank) Rite.t =
Julian-reckoning rite can supply {!Computus.julian_easter}
instead. Read by [Layer.index] for [Date_spec.Easter_offset]. *)
easter = Colitur_kernel.Computus.gregorian_easter;
+ (* The calendarium's own bissextile footnote (February, LT.txt:5011-5014):
+ see {!Temporal_ef.bissextile_fixed_key} for the full citation and
+ mechanism. Read by [Layer.on_date]'s fixed half only. *)
+ fixed_key = Temporal_ef.bissextile_fixed_key;
rules =
{ Precedence.band = Precedence_ef.band;
disposition = Precedence_ef.disposition;
diff --git a/lib/rites/rite_ef/temporal_ef.ml b/lib/rites/rite_ef/temporal_ef.ml
index c16732b..1c916f4 100644
--- a/lib/rites/rite_ef/temporal_ef.ml
+++ b/lib/rites/rite_ef/temporal_ef.ml
@@ -1158,6 +1158,68 @@ let anchors y =
| Some d -> [ ("ef-holy-name-sunday", d) ]
| None -> [ ("ef-holy-name", holy_name_fallback_date y) ])
+(* The Missale Romanum's own CALENDARIUM table, February, footnote
+ (docs/research/LT.txt:5011-5014, scan-corroborated at
+ docs/research/scan2.txt:3050-3058, where OCR mangles it to
+ "bi&sextili"/"Matthue"/"Cabrielis" -- transcription and scan agree, so
+ this rests on two witnesses of the same document):
+
+ "In anno bissextili mensis februarius est dierum 29, et festum S.
+ Matthiae celebratur die 25 februarii, ac festum S. Gabrielis a
+ Virgine perdolente 28 februarii, et bis dicitur sexto calendas, id
+ est die 24 et die 25; et littera dominicalis, quae assumpta fuit in
+ mense ianuario, mutetur in praecedentem..."
+
+ In a leap year February has 29 days, St Matthias is kept on 25 February
+ (not 24), St Gabriel of Our Lady of Sorrows on 28 February (not 27), and
+ the sixth kalends of March is said TWICE -- "bis dicitur sexto
+ calendas... die 24 et die 25". That last clause names the MECHANISM, not
+ two independent exceptions: the Roman calendar's intercalary day is
+ inserted by DOUBLING the sixth kalends (civil 24 February in a common
+ year), not by appending a 29th day at the month's end. Reckoned by
+ kalends position: 24 Feb = VI Kal. Mart., 25 Feb = V Kal., 26 Feb = IV
+ Kal., 27 Feb = III Kal., 28 Feb = pridie Kal. In a leap year VI Kal.
+ itself falls on TWO consecutive civil days (24th and 25th, "bis"), and
+ every kalends position after it is pushed one civil day later as a
+ result: V Kal. from 25th to 26th, IV Kal. from 26th to 27th, III Kal.
+ (Gabriel) from 27th to 28th, pridie Kal. from 28th to 29th. A feast fixed
+ at VI Kal. itself (Matthias) is kept on the SECOND occurrence, not the
+ first -- 25 February carries it, 24 February carries no fixed office at
+ all that year (confirmed against the LMS Ordo witness,
+ data/ef/expected-divergences-lms.sexp entry L3: 24 February 2024 is
+ titled plainly "EMBER SATURDAY of LENT", no Matthias anywhere near it).
+
+ IMPLEMENTED AS THE GENERAL MECHANISM, not as "shift these two named
+ feasts": only three sanctoral entries exist in 23-29 February on shipped
+ data (peter-damien the 23rd, before the doubled kalends and therefore
+ unaffected; matthias the 24th; gabriel-of-our-lady-of-sorrows the 27th),
+ so "shift the two named feasts" and "shift every fixed entry from 24
+ February" are indistinguishable on universal data -- they produce
+ identical output. They differ only for a locally-supplied entry, e.g. an
+ [--overlay] patronal feast fixed at 26 February: under the mechanism
+ reading it shifts to 27 February in a leap year (IV Kal. -> the civil day
+ IV Kal. falls on that year), exactly as a diocesan calendar compiled
+ against the same kalends convention would expect. The rubric's own text
+ states a MECHANISM ("bis dicitur sexto calendas"), not a closed list of
+ two saints, and this project has already been bitten once by a rule
+ implemented against the shipped data's coincidental shape rather than the
+ rubric itself (RG 16(a), CLAUDE.md's own carried lesson) -- so the general
+ reading is the one implemented here.
+
+ Threaded through {!Rite.t}'s [fixed_key] field, read only by
+ {!Colitur_kernel.Layer.on_date}'s FIXED half: the kernel stays
+ rite-agnostic (a Byzantine or other non-Roman rite supplies nothing and
+ is unaffected), and the MOVABLE half ({!Date_spec.Easter_offset},
+ {!Date_spec.Nth_weekday}) is untouched -- nothing in the footnote
+ concerns Easter-relative dates. *)
+let bissextile_fixed_key (d : Date.t) : (int * int) option =
+ let m = Date.month d and day = Date.day d in
+ if m = 2 && Date.is_leap (Date.year d) then
+ if day = 24 then None (* the FIRST VI Kal.: no fixed entry lands here in a leap year *)
+ else if day >= 25 && day <= 29 then Some (2, day - 1) (* the SECOND VI Kal. onward, one day later *)
+ else Some (m, day)
+ else Some (m, day)
+
(* Compile-time check that this module satisfies the kernel's rite contract. *)
module _ : Colitur_kernel.Temporal.RITE = struct
let id = id
diff --git a/lib/rites/rite_ef/temporal_ef.mli b/lib/rites/rite_ef/temporal_ef.mli
index 5e85111..2bed5b6 100644
--- a/lib/rites/rite_ef/temporal_ef.mli
+++ b/lib/rites/rite_ef/temporal_ef.mli
@@ -51,6 +51,17 @@ val week : Date.t -> int option
(** The lectionary key for a Sunday, or [None] if [d] is not a Sunday. *)
val sunday_slug : Date.t -> string option
+(** The calendarium's own bissextile (leap-year) footnote, February
+ (docs/research/LT.txt:5011-5014): in a leap year the sixth kalends of
+ March (24 February) is doubled rather than a 29th day appended, so every
+ fixed entry from 24 through 28 February is kept one civil day later than
+ usual (Matthias 24->25, Gabriel of Our Lady of Sorrows 27->28), and 24
+ February itself carries no fixed office that year. Supplied as {!Rite.t}'s
+ [fixed_key] field -- see that field's own doc comment and this function's
+ definition for the full citation and the general-mechanism-vs-two-named-
+ feasts reasoning. *)
+val bissextile_fixed_key : Date.t -> (int * int) option
+
val id : string
(** Total over 1583..9999: every date yields exactly one temporal identity. *)