diff options
| -rw-r--r-- | cmd/lectio-ef-dump/main.go | 46 | ||||
| -rw-r--r-- | internal/caldata/caldata_test.go | 307 | ||||
| -rw-r--r-- | internal/caldata/tridentine-calendar.ini | 66 | ||||
| -rw-r--r-- | internal/calendar/calendar.go | 124 | ||||
| -rw-r--r-- | internal/calendar/oracle_ef_test.go | 259 | ||||
| -rw-r--r-- | internal/calendar/precedence_ef.go | 86 | ||||
| -rw-r--r-- | internal/calendar/precedence_ef_repro_test.go | 160 | ||||
| -rw-r--r-- | internal/calendar/precedence_ef_test.go | 67 | ||||
| -rw-r--r-- | internal/calendar/temporal_ef.go | 81 | ||||
| -rw-r--r-- | internal/calendar/temporal_ef_test.go | 92 | ||||
| -rw-r--r-- | internal/calendar/testdata/oracle-ef.json | 7770 | ||||
| -rwxr-xr-x | scripts/build-oracle-ef.sh | 56 | ||||
| -rw-r--r-- | scripts/gen-sanctoral-ef.go | 472 |
13 files changed, 6631 insertions, 2955 deletions
diff --git a/cmd/lectio-ef-dump/main.go b/cmd/lectio-ef-dump/main.go index 08ff547..e7d014a 100644 --- a/cmd/lectio-ef-dump/main.go +++ b/cmd/lectio-ef-dump/main.go @@ -1,10 +1,25 @@ // Command lectio-ef-dump prints lectio's Extraordinary Form (1962) calendar, // one line per day, for use as colitur's differential oracle. // -// Output format matches colitur's `colitur day <year>` line for line (see -// colitur's bin/main.ml, day_line), so the two streams are diffable directly: +// Output format is colitur's `colitur day <year>` line, PLUS two display-name +// columns colitur's own line does not carry (so a straight `diff` against +// colitur's output must ignore trailing fields, not compare them line for +// line): // -// YYYY-MM-DD weekday season week slug rank colour [+other-slug]... +// YYYY-MM-DD weekday season week slug rank colour name_en name_pl [+other-slug]... +// +// name_en and name_pl are the observed celebration's own display name in +// English and Polish (Celebration.Name["en"]/["pl"]), spaces replaced with +// "_" so the line stays whitespace-delimited; "-" where the name is empty +// (a bare feria with no proper name). Added after a regeneration of +// internal/caldata/tridentine-calendar.ini once deleted all 322 Polish +// names (name.pl 322 -> 0) with nothing in this repository's test suite OR +// this dumper noticing: the season/rank/colour columns this tool already +// printed were all still correct, since name is a wholly separate field +// naming.CelebrationName reads independently. This dumper is what the +// task's own before/after diff verification is run against, so it needed +// to be structurally capable of seeing a name regression, not just told to +// look harder next time. // // Every column carries lectio's OWN vocabulary (season names, slugs, rank and // colour spellings) -- this dumper does not translate lectio's values into @@ -79,17 +94,30 @@ func run(args []string, stdout, stderr io.Writer) int { return 0 } -// dumpLine renders one LiturgicalDay as a colitur-format line. Week is -// lectio's own int (0 where no season week applies, e.g. named I class feasts -// and per annum green-season ferias); printed as "-" there so the field count -// stays fixed, matching colitur's own convention for an absent week. +// dumpName renders a display-name field: spaces become "_" so the line stays +// whitespace-delimited (names routinely contain spaces, e.g. "St. Thomas +// Becket", "Wniebowzięcie N. M. P."); "-" for an empty name, matching the +// week column's own convention for "absent". +func dumpName(s string) string { + if s == "" { + return "-" + } + return strings.ReplaceAll(s, " ", "_") +} + +// dumpLine renders one LiturgicalDay as a colitur-format line, plus the +// name_en/name_pl columns colitur's own line does not carry (see this +// package's doc comment). Week is lectio's own int (0 where no season week +// applies, e.g. named I class feasts and per annum green-season ferias); +// printed as "-" there so the field count stays fixed, matching colitur's +// own convention for an absent week. func dumpLine(day calendar.LiturgicalDay) string { week := "-" if day.Week != 0 { week = strconv.Itoa(day.Week) } var b strings.Builder - fmt.Fprintf(&b, "%s %s %s %s %s %s %s", + fmt.Fprintf(&b, "%s %s %s %s %s %s %s %s %s", day.Date.Format("2006-01-02"), strings.ToLower(day.Weekday.String()), string(day.Season), @@ -97,6 +125,8 @@ func dumpLine(day calendar.LiturgicalDay) string { day.Observed.Slug, string(day.Observed.Rank), string(day.Colour), + dumpName(day.Observed.Name["en"]), + dumpName(day.Observed.Name["pl"]), ) for _, o := range day.Others { fmt.Fprintf(&b, " +%s", o.Slug) diff --git a/internal/caldata/caldata_test.go b/internal/caldata/caldata_test.go index 12aa765..7dbbf84 100644 --- a/internal/caldata/caldata_test.go +++ b/internal/caldata/caldata_test.go @@ -74,9 +74,13 @@ func TestTridentineLoads(t *testing.T) { t.Fatalf("EF sanctoral has only %d entries; expected the full calendar", len(l.Cels)) } // Landmark feasts must be present with the right rank/class: Sts Peter & Paul - // (I class, 06-29), the Purification/Presentation (a II class feast of the - // Lord, 02-02, which must displace a Sunday), the Immaculate Conception - // (I class, 12-08). + // (I class, 06-29), the Purification/Presentation (II class, 02-02, class + // = lord -- see classOf's own doc comment in scripts/gen-sanctoral-ef.go + // for why: the calendarium's own title names the BLESSED VIRGIN, but the + // tag exists to drive OCCURRENCE behaviour, and missalemeum -- this + // data's own oracle -- shows the Purification taking a II-class Sunday's + // place outright, the "festum Domini" pattern, not the ordinary-BVM + // pattern), the Immaculate Conception (I class, 12-08). want := map[string]struct{ date, rank, class string }{ "sts-peter-paul": {"06-29", "class-1", ""}, "purification-of-the-blessed-virgin-mary": {"02-02", "class-2", "lord"}, @@ -91,7 +95,7 @@ func TestTridentineLoads(t *testing.T) { if rc.Fields["date"] != w.date || rc.Fields["rank"] != w.rank { t.Errorf("%s: date/rank = %q/%q, want %q/%q", slug, rc.Fields["date"], rc.Fields["rank"], w.date, w.rank) } - if w.class != "" && rc.Fields["class"] != w.class { + if rc.Fields["class"] != w.class { t.Errorf("%s: class = %q, want %q", slug, rc.Fields["class"], w.class) } } @@ -103,3 +107,298 @@ func TestTridentineLoads(t *testing.T) { } } } + +// TestTridentineClassOfLord: scripts/gen-sanctoral-ef.go's classOf tags +// feasts of the Lord (class = lord). "Most Holy Name of Mary" was wrongly +// tagged lord (a title-substring false positive: "holy name" alone matches +// both "Holy Name of Jesus" and "Most Holy Name of MARY", calendarium +// "Sanctissimi Nominis Mariae") and is fixed here, not contested. The +// Baptism commemoration was missing the tag entirely (13 January's title +// ends "of THE Lord", not "of OUR Lord", the only suffix classOf used to +// check -- calendarium "IN COMMEMORATIONE BAPTISMATIS D. N. I. C."), also +// fixed and not contested. The Purification is DELIBERATELY absent from +// this table: it stays tagged lord, on occurrence-behaviour evidence, not +// the calendarium's title -- see TestTridentineLoads and classOf's own doc +// comment in scripts/gen-sanctoral-ef.go for the full account of why it is +// the one contested case, not a clean-cut fix. +func TestTridentineClassOfLord(t *testing.T) { + l := Tridentine() + want := map[string]string{ + "most-holy-name-of-mary": "", // BVM, not the Lord + "commemoration-of-the-baptism-of-the-lord": "lord", + } + for slug, wantClass := range want { + rc, ok := l.Cels[slug] + if !ok { + t.Errorf("missing landmark feast %q", slug) + continue + } + if got := rc.Fields["class"]; got != wantClass { + t.Errorf("%s: class = %q, want %q", slug, got, wantClass) + } + } +} + +// TestTridentineLentRankNotCommemoration: 15 III-class feasts, every one +// falling 6 March - 5 April, were tagged rank = commemoration because all +// six of the generator's reference years happen to place that fixed date +// within Lent, where a privileged Lenten feria always outranks an +// equal-class feast (RG 109(e)) -- the generator mistook "how the entry +// presented on the sampled days" for the entry's true, intrinsic rank. A +// sample of the 15 (full list in the report); the calendarium gives each one +// III class outright, e.g. 5 April "S. Vincentii Ferrerii Conf., III +// classis." +func TestTridentineLentRankNotCommemoration(t *testing.T) { + l := Tridentine() + for _, slug := range []string{ + "sts-felicitas-perpetua", "thomas-aquinas", "frances-rome", + "gregory-the-great", "patrick", "benedict", "francis-of-paola", + "isidore-of-seville", "vincent-ferrer", + } { + rc, ok := l.Cels[slug] + if !ok { + t.Errorf("missing %q", slug) + continue + } + if got := rc.Fields["rank"]; got != "class-3" { + t.Errorf("%s: rank = %q, want class-3 (not commemoration)", slug, got) + } + } +} + +// TestTridentineGenuineCommemorationStaysCommemoration: the fix above must +// NOT promote every commemoration-only entry indiscriminately -- some really +// are without an independent Mass in the 1960-reformed books, demoted even +// on an ORDINARY, unprivileged day (not explained by Lent/Passiontide or any +// higher-class temporal day). St Blaise (3 Feb, an ordinary Septuagesima- +// season feria) is live-confirmed by missalemeum as a mere commemoration +// even then, so RankCommemoration is the honest, correct rank -- promoting +// him to class-4 would let him wrongly win an ordinary green-season feria he +// has no independent Mass to celebrate. +func TestTridentineGenuineCommemorationStaysCommemoration(t *testing.T) { + l := Tridentine() + rc, ok := l.Cels["blaise"] + if !ok { + t.Fatal("missing blaise") + } + if got := rc.Fields["rank"]; got != "commemoration" { + t.Errorf("blaise: rank = %q, want commemoration (genuinely no independent Mass)", got) + } +} + +// TestTridentineNoMissingEntries: four entries present in missalemeum (and +// so in the calendarium) were silently dropped by the generator's own +// dedup, which keyed a single global map by SLUG alone -- two by a literal +// slug collision with an unrelated feast of the same English title on a +// different date (28 January's "St. Agnes", the traditional SECOND +// commemoration of 21 January's own Agnes; 14 May's "St. Boniface", a +// different martyr from 5 June's Boniface of Mainz), and two (Evaristus, +// Theodore) by the generator returning on the first reference year that +// showed an observed office, before ever reaching the later year that +// revealed their commemoration. +func TestTridentineNoMissingEntries(t *testing.T) { + l := Tridentine() + want := map[string]string{ + "agnes-secundo": "01-28", + "boniface-martyr": "05-14", + "evaristus": "10-26", + "theodore": "11-09", + } + for slug, date := range want { + rc, ok := l.Cels[slug] + if !ok { + t.Errorf("missing %q (%s)", slug, date) + continue + } + if got := rc.Fields["date"]; got != date { + t.Errorf("%s: date = %q, want %q", slug, got, date) + } + } +} + +// TestTridentineRomanusAndEusebiusPresent: CORRECTED after review found the +// opposite claim resting on an incomplete primary-source check. An earlier +// version of this test (and of scripts/gen-sanctoral-ef.go's +// knownSpuriousComm) asserted Romanus ABSENT, on the strength of ONE of the +// three local Missal scans -- "1962-06-23,…LT.pdf", an ELECTRONIC +// TRANSCRIPTION that silently drops vigil commemorations generally (also +// missing: 7 August Donatus, 25 December Anastasia, both present elsewhere). +// The other two, PHOTOGRAPHIC scans of the actual 1962 Missale Romanum, both +// carry it: "missale-romanum-1962.pdf" calendarium, 9 August row: "XVI d V +// 9 Vigilia, III classis, Commemoratio S. Romani Mart.", with the saint's +// own proper text elsewhere in the same scan ("Et fit commemoratio S. Romani +// Mar-"), and its own back-of-book index ("Romani Mart., 9 augusti ... 621"). +// Where the scans and the transcription disagree, the scans win -- see +// gen-sanctoral-ef.go's own primary-source note, same rule recorded there so +// it is not lost a second time. +// +// 14 August's "St. Eusebius" is the identical shape (calendarium: "XI b XIX +// 14 Vigilia, II classis, Commemoratio S. Eusebii Conf.") and a DIFFERENT +// person from 16 December's "St. Eusebius, Ep. et Mart." (calendarium: "V +// XVII S. Eusebii Ep. et Mart., III classis.") -- a Confessor and a Bishop +// and Martyr, not the same saint moved or duplicated. missalemeum gives both +// the same bare English title, so they collide by slug; slugOverride +// disambiguates rather than either being dropped. +func TestTridentineRomanusAndEusebiusPresent(t *testing.T) { + l := Tridentine() + if rc, ok := l.Cels["romanus"]; !ok { + t.Error("romanus missing: the calendarium's photographic scans both carry \"Commemoratio S. Romani Mart.\" on 9 August") + } else if rc.Fields["date"] != "08-09" { + t.Errorf("romanus: date = %q, want 08-09", rc.Fields["date"]) + } + want := map[string]struct{ date, rank string }{ + // St Eusebius Confessor (14 Aug) and St Romanus (9 Aug, checked + // above) are both bare "Commemoratio" in the calendarium (no class + // of their own) -- pinned here, not just presence/date, per + // TestTridentineCommemorationRanksPinned's own reasoning below: + // romanus's own rank is pinned there instead, since that test + // groups every commemoration-rank entry this task's fixes touched + // in one place. eusebius-confessor is listed here because it is + // the OTHER half of this specific test's own slug-disambiguation + // story. + "eusebius-confessor": {"08-14", "commemoration"}, // "S. Eusebii Conf." -- a Confessor + "eusebius": {"12-16", "class-3"}, // "S. Eusebii Ep. et Mart." -- a Bishop and Martyr, a different person, unaffected by this round + } + for slug, w := range want { + rc, ok := l.Cels[slug] + if !ok { + t.Errorf("missing %q (%s)", slug, w.date) + continue + } + if rc.Fields["date"] != w.date { + t.Errorf("%s: date = %q, want %q", slug, rc.Fields["date"], w.date) + } + if rc.Fields["rank"] != w.rank { + t.Errorf("%s: rank = %q, want %q", slug, rc.Fields["rank"], w.rank) + } + } +} + +// TestTridentineCommemorationRanksPinned: nothing in this test suite +// asserted `rank` for thomas-becket, silvester, or romanus before this -- +// `TestTridentineRomanusAndEusebiusPresent` above pinned presence and date +// for romanus but not rank, and Thomas Becket/Silvester (the I3 fix, RG +// 68(d)/(e)) had no rank assertion anywhere at all. So a future +// regeneration could silently rewrite any of the three back to class-4 -- +// the EXACT I3 failure mode -- with the suite green throughout. Pinned +// together because they are the same failure shape (a bare "Commemoratio" +// in the calendarium, no class of its own, silently promoted by +// refYearExplainsAbsence's own coupling to temporal_ef.go, see that +// function's doc comment) even though they were found in two different +// review rounds (romanus in C2, Thomas Becket/Silvester in I3). +func TestTridentineCommemorationRanksPinned(t *testing.T) { + l := Tridentine() + for _, slug := range []string{"romanus", "thomas-becket", "silvester"} { + rc, ok := l.Cels[slug] + if !ok { + t.Errorf("missing %q", slug) + continue + } + if rc.Fields["rank"] != "commemoration" { + t.Errorf("%s: rank = %q, want commemoration", slug, rc.Fields["rank"]) + } + } +} + +// TestTridentineNoTransferArtifacts: a movable-transfer feast displayed on +// whatever civil date it actually landed on in a given reference year (St +// Joseph pushed to 20 March by a Sunday of Lent; the Annunciation deferred +// past Holy Week; All Souls moved to the Monday; St Matthias shown on the +// 25th in a leap year) must not leak into the sanctoral as a phantom +// fixed-date entry keyed to that transferred civil date. +func TestTridentineNoTransferArtifacts(t *testing.T) { + l := Tridentine() + for _, slug := range []string{ + "joseph-spouse-of-the-bl-virgin-mary-0320", + "annunciation-of-the-blessed-virgin-mary-0405", + "annunciation-of-the-blessed-virgin-mary-0408", + "annunciation-of-the-blessed-virgin-mary-0409", + "commemoration-of-all-souls-1103", + "matthias-0225", + } { + if _, ok := l.Cels[slug]; ok { + t.Errorf("phantom transfer-artifact entry %q present", slug) + } + } +} + +// TestTridentineNamesPreservedAcrossRegeneration is the coverage guard a +// regeneration silently destroying a whole language's names needed and did +// not have: an earlier version of scripts/gen-sanctoral-ef.go's main() +// preserved existing name.la values across a regeneration (missalemeum +// supplies English only) but had no equivalent for name.pl -- and, because +// the bootstrapped file has in fact never carried a name.la value, that +// mechanism looked correct while doing nothing at all. A regeneration +// deleted all 322 Polish names outright (name.pl count 322 -> 0), silently: +// no test here asserted anything about a name.* field, and +// `len(l.Cels) < 250` (TestTridentineLoads) does not notice a field going +// missing within entries that still exist. `naming.CelebrationName`'s own +// name[lang] -> name.en fallback (internal/naming/naming.go) then quietly +// substituted English for Polish on every EF display in that language, +// reaching mobile.Day(date, "ef", version, "pl") -- a shipped dlectio entry +// point -- with no error anywhere in the chain. +// +// CORRECTED after review: the first version of this test counted name.pl +// only (a hardcoded single language -- the exact "whitelist of two +// languages" mistake C1's own fix was written to stop repeating, just +// moved into the test), and its coverage floor (>= 315) had 7 entries of +// slack -- the review proved dropping 6 entries' Polish names still passed +// it. Fixed on both axes: the language set is DISCOVERED from the data +// (every "name.<lang>" key actually present, not a hardcoded list, so a +// regeneration dropping name.la or introducing a future name.de is +// checked the same way as name.pl), and the floor for each discovered +// language is its EXACT true count, not a loose approximation -- verified +// directly against the branch point (`git show 2386a45:...`) once, by +// hand, and hardcoded as the answer, not derived at test time from data +// that could itself be wrong. +// +// True counts, independently verified: name.en on every entry (327, all +// regenerated fresh from missalemeum, including the 5 entries this task's +// own fixes added); name.pl on exactly 322 (preserved from the branch +// point; the 5 new entries -- St Agnes secundo, St Boniface Martyr, St +// Evaristus, St Theodore, St Eusebius Confessor -- never had a curated +// Polish name to preserve in the first place, so 322, not 327, is the +// correct target, not a shortfall); no OTHER name.<lang> exists in the +// branch point at all (name.la is read by the generator but the +// bootstrapped file has in fact never carried one), so the discovered +// language set itself must be exactly {en, pl} -- a regeneration that +// silently introduced or lost an entire language key, not just some +// values within one, is caught by this assertion, not only by the count. +func TestTridentineNamesPreservedAcrossRegeneration(t *testing.T) { + l := Tridentine() + counts := map[string]int{} + for _, rc := range l.Cels { + for k, v := range rc.Fields { + if v == "" || !strings.HasPrefix(k, "name.") { + continue + } + lang := strings.TrimPrefix(k, "name.") + counts[lang]++ + } + } + wantLangs := map[string]bool{"en": true, "pl": true} + for lang := range counts { + if !wantLangs[lang] { + t.Errorf("unexpected name.%s present (%d entries) -- discovered language set must be exactly {en, pl}", lang, counts[lang]) + } + } + for lang := range wantLangs { + if counts[lang] == 0 { + t.Errorf("name.%s entirely absent -- discovered language set must be exactly {en, pl}", lang) + } + } + if got := counts["en"]; got != len(l.Cels) { + t.Errorf("name.en coverage = %d entries, want %d (every entry, all freshly regenerated)", got, len(l.Cels)) + } + if got := counts["pl"]; got != 322 { + t.Errorf("name.pl coverage = %d entries, want exactly 322 (the branch point's own true count; the 5 entries this task added have no curated Polish name to preserve, so more or fewer than 322 is a bug either way)", got) + } + + rc, ok := l.Cels["assumption-of-the-blessed-virgin-mary"] + if !ok { + t.Fatal("missing assumption-of-the-blessed-virgin-mary") + } + if got := rc.Fields["name.pl"]; got != "Wniebowzięcie N. M. P." { + t.Errorf("assumption-of-the-blessed-virgin-mary: name.pl = %q, want the preserved Polish name", got) + } +} diff --git a/internal/caldata/tridentine-calendar.ini b/internal/caldata/tridentine-calendar.ini index 3fb61d7..55564d7 100644 --- a/internal/caldata/tridentine-calendar.ini +++ b/internal/caldata/tridentine-calendar.ini @@ -4,7 +4,9 @@ ; by internal/calendar (temporalEF) and is NOT listed here. ; Ranks use the 1960 Code of Rubrics: class-1..class-4. ; Generated by scripts/gen-sanctoral-ef.go from missalemeum (Divinum Officium 1962 -; data). Latin names are hand-curated where present. See NOTICE. +; data). name.en is always regenerated fresh from missalemeum; every other +; name.<lang> (missalemeum supplies English only) is preserved verbatim from +; whatever this file already carried before regeneration. See NOTICE. [layer] id = tridentine @@ -29,6 +31,7 @@ name.pl = św. Hygina, Papieża i Męczennika date = 01-13 rank = class-2 colour = white +class = lord name.en = Commemoration of the Baptism of the Lord name.pl = Wspomnienie Chrztu Pańskiego reading.first = Isa 60:1-6 @@ -191,6 +194,12 @@ name.pl = św. Jana Chryzostoma, Wyznawcy, Biskupa i Doktora Kościoła reading.first = 2 Tim 4:1-8 reading.gospel = Matt 5:13-19 +[agnes-secundo] +date = 01-28 +rank = commemoration +colour = red +name.en = St. Agnes + [peter-nolasco] date = 01-28 rank = class-3 @@ -430,56 +439,56 @@ name.pl = św. Lucjusza I, Papieża i Męczennika [sts-felicitas-perpetua] date = 03-06 -rank = commemoration +rank = class-3 colour = red name.en = Sts. Felicitas & Perpetua name.pl = śś. Perpetui i Felicyty, Męczennic [thomas-aquinas] date = 03-07 -rank = commemoration +rank = class-3 colour = white name.en = St. Thomas Aquinas name.pl = św. Tomasza z Akwinu, Wyznawcy i Doktora Kościoła [john-of-god] date = 03-08 -rank = commemoration +rank = class-3 colour = white name.en = St. John of God name.pl = św. Jana Bożego, Wyznawcy [frances-rome] date = 03-09 -rank = commemoration +rank = class-3 colour = white name.en = St. Frances Rome name.pl = św. Franciszki Rzymianki, Wdowy [forty-holy-martyrs-of-sebaste] date = 03-10 -rank = commemoration +rank = class-3 colour = red name.en = Forty Holy Martyrs of Sebaste name.pl = śś. Czterdziestu Męczenników [gregory-the-great] date = 03-12 -rank = commemoration +rank = class-3 colour = white name.en = St. Gregory the Great name.pl = św. Grzegorza Wielkiego, Papieża, Wyznawcy i Doktora Kościoła [patrick] date = 03-17 -rank = commemoration +rank = class-3 colour = white name.en = St. Patrick name.pl = św. Patryka, Biskupa i Wyznawcy [cyril-of-jerusalem] date = 03-18 -rank = commemoration +rank = class-3 colour = white name.en = St. Cyril of Jerusalem name.pl = św. Cyryla Jerozolimskiego, Biskupa, Wyznawcy i Doktora Kościoła @@ -495,14 +504,14 @@ reading.gospel = Matt 1:18-21 [benedict] date = 03-21 -rank = commemoration +rank = class-3 colour = white name.en = St. Benedict name.pl = św. Benedykta, Opata [gabriel-the-archangel] date = 03-24 -rank = commemoration +rank = class-3 colour = white name.en = St. Gabriel the Archangel name.pl = św. Gabriela Archanioła @@ -518,35 +527,35 @@ reading.gospel = Luke 1:26-38 [john-damascene] date = 03-27 -rank = commemoration +rank = class-3 colour = white name.en = St. John Damascene name.pl = św. Jana Damasceńskiego, Wyznawcy i Doktora Kościoła [john-of-capistrano] date = 03-28 -rank = commemoration +rank = class-3 colour = white name.en = St. John of Capistrano name.pl = św. Jana Kapistrana, Wyznawcy [francis-of-paola] date = 04-02 -rank = commemoration +rank = class-3 colour = white name.en = St. Francis of Paola name.pl = św. Franciszka z Pauli, Wyznawcy [isidore-of-seville] date = 04-04 -rank = commemoration +rank = class-3 colour = white name.en = St. Isidore of Seville name.pl = św. Izydora, Biskupa, Wyznawcy i Doktora Kościoła [vincent-ferrer] date = 04-05 -rank = commemoration +rank = class-3 colour = white name.en = St. Vincent Ferrer name.pl = św. Wincentego Fereriusza, Wyznawcy @@ -784,6 +793,12 @@ name.pl = św. Roberta Bellarmina, Biskupa, Wyznawcy i Doktora Kościoła reading.first = Wis 7:7-14. reading.gospel = Matt 5:13-19 +[boniface-martyr] +date = 05-14 +rank = commemoration +colour = red +name.en = St. Boniface + [john-baptist-de-la-salle] date = 05-15 rank = class-3 @@ -1596,6 +1611,12 @@ colour = red name.en = Sts. Hippolytus & Cassian name.pl = śś. Hipolita i Kasjana, Męczenników +[eusebius-confessor] +date = 08-14 +rank = commemoration +colour = red +name.en = St. Eusebius + [vigil-of-the-assumption] date = 08-14 rank = class-2 @@ -1866,7 +1887,6 @@ name.pl = św. Prota i Jacka, Męczenników date = 09-12 rank = class-3 colour = white -class = lord name.en = Most Holy Name of Mary name.pl = Najświętszego Imienia Maryi reading.first = Sir 24:23-31 @@ -2264,6 +2284,12 @@ colour = red name.en = Sts. Chrysanthus & Daria name.pl = śś. Chryzanta i Darii, Męczenników +[evaristus] +date = 10-26 +rank = commemoration +colour = red +name.en = St. Evaristus + [sts-simon-jude] date = 10-28 rank = class-2 @@ -2324,6 +2350,12 @@ name.pl = Rocznica Konsekracji Bazyliki Najświętszego Zbawiciela na Lateranie reading.first = Rev 21:2-5 reading.gospel = Luke 19:1-10 +[theodore] +date = 11-09 +rank = commemoration +colour = red +name.en = St. Theodore + [andrew-avellino] date = 11-10 rank = class-3 diff --git a/internal/calendar/calendar.go b/internal/calendar/calendar.go index 33706d8..2d8611a 100644 --- a/internal/calendar/calendar.go +++ b/internal/calendar/calendar.go @@ -35,14 +35,43 @@ func TemporalSlug(date time.Time, sel Selection) string { func computeEF(date time.Time, sel Selection, layers []Layer) LiturgicalDay { td := temporalEF(date) merged := mergeLayers(layers) - cands := []candidate{{Cel: td.Cel, Temporal: true, Season: td.Season}} + year := date.Year() + // occupiedByRank reports whether some OTHER fixed-date sanctoral + // celebration whose rank passes `allowed` resolves onto d this year. + // transferIfImpededEF uses this at two different thresholds: class 1 + // only, to decide whether a candidate is impeded in the first place (a + // class-2 occupant never impedes a class-1 feast -- class 1 always beats + // class 2 outright, no tie exists); and class 1 OR 2, for RG 96's "next + // day that is not I or II class" once a transfer is already under way + // (e.g. the Visitation, 2 July, blocking the Precious Blood's transfer + // off 1 July in 2011). + occupiedByRank := func(d time.Time, exceptSlug string, allowed func(Rank) bool) bool { + for slug2, rc2 := range merged { + if slug2 == exceptSlug { + continue + } + cel2 := buildCelebration(slug2, rc2) + if !allowed(cel2.Rank) { + continue + } + if when2, ok := celebrationDate(cel2, year, sel); ok && sameDay(when2, d) { + return true + } + } + return false + } + isClass1 := func(r Rank) bool { return r == RankClass1 } + isClass1Or2 := func(r Rank) bool { return r == RankClass1 || r == RankClass2 } + cands := []candidate{{Cel: td.Cel, Temporal: true, Season: td.Season, Sunday: td.Sunday}} for slug, rc := range merged { cel := buildCelebration(slug, rc) - when, ok := celebrationDate(cel, date.Year(), sel) + when, ok := celebrationDate(cel, year, sel) if !ok { continue } - effective := transferIfImpededEF(cel, when) + effective := transferIfImpededEF(cel, when, + func(d time.Time) bool { return occupiedByRank(d, cel.Slug, isClass1) }, + func(d time.Time) bool { return occupiedByRank(d, cel.Slug, isClass1Or2) }) if sameDay(effective, date) { cands = append(cands, candidate{Cel: cel, Temporal: false, Season: td.Season}) } @@ -199,12 +228,54 @@ func transferIfImpeded(cel Celebration, when time.Time, sel Selection) time.Time // transferIfImpededEF moves an EF sanctoral feast off a date it cannot be kept // on. Two rules cover the 1962 cases: All Souls, when Nov 2 is a Sunday, is -// transferred to the Monday (Nov 3); and a I class feast impeded by a I class -// temporal day (Holy Week, the Easter octave) is pushed forward to the next free -// day — for the Annunciation in Holy Week this lands on the Monday after Low -// Sunday, past the whole privileged octave. Lower-rank feasts are only -// commemorated, never transferred. -func transferIfImpededEF(cel Celebration, when time.Time) time.Time { +// transferred to the Monday (Nov 3); and a I class feast genuinely impeded is +// pushed forward to the next day that is itself neither I nor II class (RG +// 96: "the next following day that is not I or II class"). Lower-rank feasts +// are only commemorated, never transferred (RG 95). +// +// occupiedByClass1 and occupiedByClass1Or2 are deliberately different +// thresholds, not the same check reused twice: +// - a candidate is impeded IN THE FIRST PLACE only by a genuine class-1 +// collision -- the temporal office of `when` is itself I class (a Sunday +// of Advent/Lent/Passiontide, Holy Week, a named I-class feast), or +// another FIXED I-class sanctoral feast already sits on `when` (RG +// 97/98). A II-class occupant, temporal or sanctoral, never impedes a +// I-class feast at all -- I class always outranks II class outright, no +// tie-break is even reached -- so using the wider I-OR-II threshold here +// would (and, before this fix, did: e.g. All Saints, 1 Nov, was wrongly +// bumped to 3 Nov merely for landing on an ordinary II-class Sunday it +// would have won outright) send an unimpeded I-class feast on an +// unnecessary walk. +// - once a transfer is under way, the DESTINATION must avoid landing on +// ANY I- or II-class day (RG 96's own wider "not I or II class" text) -- +// e.g. the Visitation, 2 July, blocks the Precious Blood's transfer off 1 +// July in 2011, and 3 July's ordinary Sunday blocks it a second time. +// +// KNOWN GAP, not fixed here (recorded per RG 95, so the next person does not +// have to rediscover it from scratch): this function resolves ONE +// candidate's own transfer walk in isolation. It has no way to notice that a +// SECOND, separately-transferred I-class candidate has landed on the exact +// same destination day. Concretely: St Joseph (19 March) and the +// Annunciation (25 March) can both be walked, independently, to the Monday +// after Low Sunday in the same year (2008, 2035, 2046 -- e.g. 2035-04-02: +// `annunciation-of-the-blessed-virgin-mary … +joseph-spouse-of-the-bl-virgin-mary`). +// RG 95 grants the right of translation "solummodo festis I classis" (to +// I-class feasts ONLY) -- so BOTH have that right, and the day they land on +// together is itself an ordinary occurrence collision RG 97/98 governs (the +// higher table position is kept, the other transfers FURTHER): this +// function does not re-walk the loser, it lets pickEF's plain alphabetical +// slug tie-break settle it, so the loser is merely commemorated instead of +// continuing its own walk one more day. RG 98 itself supplies the missing +// determinism rule for the tie this collision even needs: "in paritate +// autem Officium prius impeditum praecedit" -- at equal table position, the +// office impeded FIRST takes precedence -- which is chronological (Joseph, +// impeded on the 19th, before the Annunciation's own walk begins on the +// 25th) and may favour Joseph over pickEF's alphabetical fallback. Neither +// RG 98's tie rule nor the re-walk RG 97 implies is implemented; fixing this +// properly means resolving occurrence between two ALREADY-TRANSFERRED +// candidates, not a single one, which is out of this function's current +// shape. +func transferIfImpededEF(cel Celebration, when time.Time, occupiedByClass1, occupiedByClass1Or2 func(time.Time) bool) time.Time { if when.Month() == time.November && when.Day() == 2 && when.Weekday() == time.Sunday && strings.Contains(cel.Slug, "all-souls") { return when.AddDate(0, 0, 1) @@ -212,11 +283,40 @@ func transferIfImpededEF(cel Celebration, when time.Time) time.Time { if cel.Rank != RankClass1 { return when } - day := when + // Is cel actually impeded on `when` at all? Compare its OWN precedence + // (via precedenceEF, the same function pickEF uses to decide the day) + // against the temporal office's, rather than testing the temporal + // office's class in isolation -- a plain "is the temporal day I class" + // test wrongly impedes a candidate that would in fact WIN a tie against + // it: RG 91 entry 4 (the Immaculate Conception, the Assumption) sits + // ABOVE entry 6 (Sundays), so the Immaculate Conception is not impeded + // by the Advent Sunday it may fall on at all, unlike an ordinary I-class + // feast (entry 11, e.g. St Joseph), which is. occupiedByClass1 still + // covers the separate case of a competing FIXED I-class SANCTORAL + // feast, which this temporal-only comparison cannot see. + startTemporal := temporalEF(when) + tCand := candidate{Cel: startTemporal.Cel, Temporal: true, Season: startTemporal.Season, Sunday: startTemporal.Sunday} + sCand := candidate{Cel: cel, Temporal: false} + startImpeded := precedenceEF(tCand) < precedenceEF(sCand) || occupiedByClass1(when) + if !startImpeded { + return when + } + day := when.AddDate(0, 0, 1) for i := 0; i < 30; i++ { b := temporalEF(day) - if precedenceEF(candidate{Cel: b.Cel, Temporal: true, Season: b.Season}) <= 2 { - day = day.AddDate(0, 0, 1) // impeded by a I class temporal day; push forward + // A direct CLASS test, not precedenceEF's tie-break band: band + // encodes which of two EQUAL-class candidates wins a tie (e.g. a + // Sunday beats an equal-class feast, but a privileged Ember/late- + // Advent FERIA of the same class yields to one, defect 2) -- an + // unrelated question from RG 96's own "is this day itself I or II + // class" test. Reusing band here undercounted: a day within the + // Octave of the Nativity (26-31 Dec) is genuinely II class (RG 67), + // but as an ordinary, non-Sunday II-class temporal candidate its OWN + // band yields (5, not <=3) -- so band<=3 alone let an impeded I-class + // feast wrongly land there. isHighClass tests the class directly. + isHighClass := b.Cel.Rank == RankClass1 || b.Cel.Rank == RankClass2 + if isHighClass || occupiedByClass1Or2(day) { + day = day.AddDate(0, 0, 1) // still I- or II-class; keep walking continue } return day diff --git a/internal/calendar/oracle_ef_test.go b/internal/calendar/oracle_ef_test.go index ce4badd..6d63220 100644 --- a/internal/calendar/oracle_ef_test.go +++ b/internal/calendar/oracle_ef_test.go @@ -12,11 +12,51 @@ import ( "github.com/lukaszkasprzak/lectio/internal/calendar" ) +// efOracleDay is one day of missalemeum's per-date proper API, as captured in +// sources/snapshot.tar.gz (missalemeum/en/YYYY-MM-DD.json, 2026-01-01 .. +// 2027-12-31, 730 days) and flattened by scripts/build-oracle-ef.sh. +// +// Three things about this data that will otherwise cost hours (see that +// script's own header for the full account): +// +// 1. ID looks like "sancti:MM-DD:rank:colour", but its embedded rank is the +// rank of the PROPERS USED that day, not the day's own rank -- e.g. +// 2026-01-02 is a class-4 feria carrying id "sancti:01-01:1:w" because it +// reuses the Circumcision's propers. Kept here for provenance/debugging +// ONLY. Rank and Colour comparisons below use Rank/Colours, never ID. +// 2. Colours is an array -- 14 of 730 days carry two values (Gaudete/Laetare +// "pv", Palm Sunday "rv", Good Friday "bv", Holy Saturday "vw") -- so the +// comparison is membership, not equality. +// 3. A two-colour value on a weekday can be an artifact of proper reuse (a +// feria inside Gaudete/Laetare week reusing the Sunday's own propers) +// rather than a claim about that weekday's own colour. No special-casing +// is needed for this: lectio's single ferial colour (violet) is already a +// member of the reused set (e.g. ["p","v"]), so a plain membership check +// absorbs it. type efOracleDay struct { - Tempora string `json:"tempora"` - Title string `json:"title"` - Rank int `json:"rank"` - Colour string `json:"colour"` + ID string `json:"id"` + Tempora string `json:"tempora"` + Title string `json:"title"` + Rank int `json:"rank"` + Colours []string `json:"colours"` +} + +// efColourLetters maps missalemeum's single-letter colour codes to lectio's +// Colour vocabulary (scripts/gen-sanctoral-ef.go's colourWord table, same +// mapping, kept in sync deliberately rather than imported across a +// package/build-tag boundary). +var efColourLetters = map[string]calendar.Colour{ + "w": calendar.White, "r": calendar.Red, "g": calendar.Green, + "v": calendar.Violet, "b": calendar.Black, "p": calendar.Rose, +} + +// efRankNumbers maps missalemeum's 1-4 rank number to lectio's EF Rank +// vocabulary. missalemeum has no separate "commemoration" rank number -- +// RankCommemoration is a lectio-side concept for a losing sanctoral +// candidate, never the oracle's claim about the OBSERVED day. +var efRankNumbers = map[int]calendar.Rank{ + 1: calendar.RankClass1, 2: calendar.RankClass2, + 3: calendar.RankClass3, 4: calendar.RankClass4, } // efSeasonFromString maps a missalemeum tempora/title phrase (for a day in the @@ -28,6 +68,14 @@ type efOracleDay struct { // there, not to Time after Epiphany. func efSeasonFromString(s string, month int) calendar.Season { s = strings.ToLower(s) + // missalemeum's own EN-locale text still carries the occasional Latin + // ligature (e.g. "Feria V after Sexagesimæ") -- confirmed in the + // committed snapshot: "Sexagesimæ" appears 10 times, "Sexagesima" (no + // ligature) only 4, and the ligatured form matched no case below, + // silently mapping those 10 days to season "" (skipped from coverage + // entirely, not merely a season miss). Normalising here fixes every + // current and future ligature in one place, not just this one word. + s = strings.ReplaceAll(s, "æ", "ae") has := func(subs ...string) bool { for _, sub := range subs { if strings.Contains(s, sub) { @@ -63,9 +111,116 @@ func efSeasonFromString(s string, month int) calendar.Season { } } -// TestOracleEF diffs the EF engine against missalemeum (Divinum Officium data). -// Season is asserted strictly (validates temporalEF); rank/colour are reported -// informationally (partial 1962 sanctoral). +// efAllow is one cited allow-list entry: a genuine, defensible divergence +// between lectio's EF engine and the missalemeum oracle on Rank and/or +// Colour, kept out of the pass/fail count deliberately rather than silently +// skipped. Every entry names the date(s) it covers, which field(s) it +// excuses, and why -- with an RG citation where the divergence is a rubric +// question, or a plain "not built" note where it is a documented scope gap +// (see internal/calendar/precedence_ef.go and temporal_ef.go's own doc +// comments, and colitur's rules-register.md, for the fuller accounts). +type efAllow struct { + date string // "" = pattern-matched by match(), see below + match func(date string, day time.Time, oracle efOracleDay) bool + field string // "rank", "colour", or "rank+colour" + reason string +} + +var efAllowList = []efAllow{ + { + // RG 91 entry 27, "Officium sanctae Mariae in sabbato": the votive + // BVM Office on an otherwise-unoccupied IV-class Saturday. Not built + // in lectio (temporal_ef.go constructs only a bare ferial slug on + // these Saturdays; the vocabulary comment in colitur's own register + // documents the same gap on its side). missalemeum's rank/colour for + // these Saturdays reflects the BVM Office (usually white); lectio's + // reflects the plain per-annum feria (green, class-4). A real, + // scoped, pre-existing gap -- not one of the seven defects, and not + // attempted here (a Plan-scale feature, per the sibling project's own + // parking of the identical item). + match: func(date string, day time.Time, o efOracleDay) bool { + return day.Weekday() == time.Saturday && + strings.Contains(strings.ToLower(o.Title), "b. v. m") + }, + field: "rank+colour", + reason: "RG 91 entry 27 (BVM Office on Saturday) is not built in lectio; both engines agree only that the day is unimpeded", + }, + { + // RG 72-73 place 6-13 January within Christmastide itself ("a I + // Vesperis Nativitatis Domini usque ad diem 13 ianuarii inclusive"); + // RG 119(a) backs the same boundary from the white-colour side + // ("...usque ad expletum tempus Epiphaniae"). lectio's efSeason + // (temporal_ef.go) instead starts "time after Epiphany" on 6 January, + // so a plain feria in this window gets green/TimeAfterEpiphany + // instead of white/Christmastide. This is a real, PRE-EXISTING season- + // boundary divergence -- colitur's own rules-register.md documents + // the identical gap on its side (§3c item 1) as deliberate and + // resolved in the OTHER engine's favour, not one of the seven named + // defects, and not touched here: efSeason is a season-boundary + // function with much wider reach than any of the seven, and changing + // it is out of this task's scope. + match: func(date string, day time.Time, o efOracleDay) bool { + return day.Month() == time.January && day.Day() >= 6 && day.Day() <= 13 + }, + field: "colour", + reason: "RG 72-73/RG 119(a): 6-13 Jan is Christmastide, not lectio's time-after-Epiphany reading (efSeason, not one of the seven defects; see colitur rules-register.md §3c item 1)", + }, + { + // RG 33: "Vigilia II aut III classis penitus omittitur, si occurrat in + // dominica quavis..." -- a II/III-class vigil is ENTIRELY OMITTED on + // any Sunday. 9 August 2026 is a Sunday; the Vigil of St Lawrence (III + // class) must vanish and the Sunday itself be observed -- which is + // exactly what lectio does (see cmd/lectio-ef-dump: 2026-08-09 + // observed is the II-class Sunday, the vigil demoted to a losing + // candidate). missalemeum's OWN data shows the vigil still winning + // that Sunday, an RG 33 gap on missalemeum's side, not lectio's -- + // already identified and adjudicated in the primary source's favour + // by the sibling project (rules-register.md §6, "the romanus-vs- + // vigil-of-st-lawrence 9 August Sunday tie-break", M1). + date: "2026-08-09", + field: "rank+colour", + reason: "RG 33: a II/III-class vigil is omitted on any Sunday; missalemeum itself shows an RG 33 gap here (colitur rules-register.md §6, M1) -- lectio's Sunday-observed answer is the Missal-correct one", + }, + { + // OPEN, not adjudicated by any primary text found so far. RG 91's + // plain table gives St Joseph (19 March, I class) the day outright + // over an ordinary III-class Friday of Passion Week -- no RG 96 + // collision requiring a transfer -- yet missalemeum shows Joseph + // entirely displaced in 2027 specifically (the Friday's own office + // observed, the Seven Sorrows commemorated instead). The sibling + // project's much deeper primary-source pass over the SAME question + // left it explicitly open (colitur rules-register.md §6, M13: "three + // possibilities, none confirmed") rather than guess at an unfound + // rubric. Not attempted here either, for the same reason -- adjudicating + // it would mean finding a citation that a more thorough primary-source + // audit did not. + date: "2027-03-19", + field: "rank+colour", + reason: "unresolved even by primary-source review (colitur rules-register.md §6, M13); not adjudicated here either way", + }, +} + +func efAllowed(date string, day time.Time, oracle efOracleDay, field string) (bool, string) { + for _, a := range efAllowList { + if a.date != "" && a.date != date { + continue + } + if a.match != nil && !a.match(date, day, oracle) { + continue + } + if a.field == field || a.field == "rank+colour" { + return true, a.reason + } + } + return false, "" +} + +// TestOracleEF diffs the EF engine against missalemeum (Divinum Officium data) +// over 730 days (2026-01-01 .. 2027-12-31). Season, Rank and Colour are all +// asserted strictly (membership for Colour, since missalemeum's colour is an +// array); a prior version of this test asserted Season only, which is exactly +// why several precedence/colour defects (see precedence_ef.go, temporal_ef.go) +// shipped without ever failing a test. func TestOracleEF(t *testing.T) { raw, err := os.ReadFile("testdata/oracle-ef.json") if err != nil { @@ -85,8 +240,8 @@ func TestOracleEF(t *testing.T) { } sort.Strings(dates) - var seasonMiss, skipped, total int - shown := 0 + var seasonMiss, rankMiss, colourMiss, rankAllowed, colourAllowed, skipped, total int + shownSeason, shownRank, shownColour := 0, 0, 0 for _, date := range dates { od := oracle[date] src := od.Tempora @@ -95,22 +250,92 @@ func TestOracleEF(t *testing.T) { } day, _ := time.Parse("2006-01-02", date) want := efSeasonFromString(src, int(day.Month())) - if want == "" { - skipped++ - continue - } total++ got := calendar.Compute(day.UTC(), sel, layers) - if got.Season != want { + + // An unrecognised season phrase skips the SEASON comparison only -- + // it must not also skip Rank/Colour for that day. A `continue` here + // once did exactly that, silently zeroing oracle coverage for every + // day whose phrase efSeasonFromString doesn't recognise (Holy + // Thursday -- "maundy"/"holy week" don't match "Holy Thursday" + // itself; the six September Ember days -- no "ember" case exists at + // all, only Advent/Lent Ember days pass by an incidental substring + // match on "advent"/"lent"). Reverting the Holy Thursday colour fix + // (temporal_ef.go) left this test green under the old `continue`; + // it does not under this one. + if want == "" { + skipped++ + } else if got.Season != want { seasonMiss++ - if shown < 25 { + if shownSeason < 40 { t.Errorf("%s: EF season got %q want %q (from %q)", date, got.Season, want, src) - shown++ + shownSeason++ + } + } + + wantRank, rankKnown := efRankNumbers[od.Rank] + if rankKnown && got.Observed.Rank != wantRank { + if ok, reason := efAllowed(date, day, od, "rank"); ok { + rankAllowed++ + t.Logf("[allow-listed] %s: EF rank got %q want %q — %s", date, got.Observed.Rank, wantRank, reason) + } else { + rankMiss++ + if shownRank < 40 { + t.Errorf("%s: EF rank got %q want %q (oracle rank %d, title %q)", + date, got.Observed.Rank, wantRank, od.Rank, od.Title) + shownRank++ + } + } + } + + colourOK := false + for _, c := range od.Colours { + if efColourLetters[c] == got.Colour { + colourOK = true + break + } + } + // Membership alone cannot catch a Rose regression: violet is a + // member of every rose/violet pair by construction (Gaudete/ + // Laetare), so "got violet, want one of [rose violet]" passes even + // if RG 131's Rose support (temporal_ef.go) were reverted entirely. + // On the day the rose/violet pair actually names -- oracle rank 1, + // the Sunday itself, not a weekday reusing its propers (which + // carries a lower rank and is deliberately membership-only, this + // file's own doc comment item 3) -- a colour set containing rose + // demands rose specifically, not merely "some member". + if colourOK && od.Rank == 1 && got.Colour != calendar.Rose { + for _, c := range od.Colours { + if c == "p" { + colourOK = false + break + } + } + } + if !colourOK && len(od.Colours) > 0 { + if ok, reason := efAllowed(date, day, od, "colour"); ok { + colourAllowed++ + t.Logf("[allow-listed] %s: EF colour got %q want one of %v — %s", date, got.Colour, od.Colours, reason) + } else { + colourMiss++ + if shownColour < 40 { + t.Errorf("%s: EF colour got %q want one of %v (title %q)", + date, got.Colour, od.Colours, od.Title) + shownColour++ + } } } } - t.Logf("EF oracle: %d checked, %d skipped(unmapped), %d season mismatches", total, skipped, seasonMiss) + t.Logf("EF oracle: %d checked, %d skipped(unmapped), %d season mismatches, "+ + "%d rank mismatches (%d allow-listed), %d colour mismatches (%d allow-listed)", + total, skipped, seasonMiss, rankMiss, rankAllowed, colourMiss, colourAllowed) if seasonMiss > 0 { t.Fatalf("%d/%d EF season mismatches vs missalemeum — temporalEF is wrong", seasonMiss, total) } + if rankMiss > 0 { + t.Fatalf("%d/%d EF rank mismatches vs missalemeum (not allow-listed)", rankMiss, total) + } + if colourMiss > 0 { + t.Fatalf("%d/%d EF colour mismatches vs missalemeum (not allow-listed)", colourMiss, total) + } } diff --git a/internal/calendar/precedence_ef.go b/internal/calendar/precedence_ef.go index 4fda626..9f5016f 100644 --- a/internal/calendar/precedence_ef.go +++ b/internal/calendar/precedence_ef.go @@ -1,6 +1,9 @@ package calendar -import "sort" +import ( + "sort" + "strings" +) // efRankOrder orders EF (1960) ranks: class-1 highest, then class-2..4, // commemoration, ferial lowest. @@ -22,34 +25,89 @@ func efRankOrder(r Rank) int { } // precedenceEF ranks an EF candidate for occurrence (lower = higher precedence): -// by class first, then a tie-break at equal class (1960 occurrence table). +// by class first, then a tie-break at equal class (RG 91's Table of +// Precedence, read entry-by-entry within each class). // -// The tie-break is asymmetric by season. An ORDINARY feria (per annum, Advent, -// Septuagesima) yields to an equal-class feast — the feast is celebrated and the -// feria commemorated (e.g. St Francis Xavier, Dec 3, on an Advent feria). The -// ferias of Lent and Passiontide are privileged: they outrank an equal-class -// feast, which is only commemorated. Sundays and named temporal feasts likewise -// win their ties. The *2 class spacing means the ±1 tie-break never crosses a -// class boundary. +// The tie-break is asymmetric by season AND, at class 2, by whether the +// temporal day is a Sunday or a privileged FERIA: +// - III/IV class: an ORDINARY feria (per annum, Advent to 16 Dec, +// Septuagesima) yields to an equal-class feast (entries 24/25 above the +// feria) -- the feast is celebrated, the feria commemorated (e.g. St +// Francis Xavier, Dec 3). The ferias of Lent and Passiontide are +// privileged (entry 22, ABOVE entry 24): they outrank an equal-class +// feast, which is only commemorated. +// - II class: an ordinary SUNDAY wins its tie (entry 15, above entry 16's +// feasts) -- but a II-class privileged FERIA (the Ember days, the +// late-Advent 17-23 Dec ferias, entry 18) sits BELOW entry 16 and yields +// to an equal-class feast, the opposite of a Sunday's own tie. This is +// the same table shape as III class's Advent/per-annum ferias, just +// inverted for which II-class temporal days count as "privileged". +// - I class: Sundays (entry 6) and I-class ferias (entry 7, Ash +// Wednesday/Holy Week) both sit above entry 11's feasts, so they always +// win -- there is no I-class "ordinary feria yields" case at all. +// +// The *2 class spacing means the ±1 tie-break never crosses a class boundary. func precedenceEF(c candidate) int { p := (6 - efRankOrder(c.Cel.Rank)) * 2 // class-1 -> 2, ferial -> 12 if c.Temporal { - ordinaryFeria := (c.Cel.Rank == RankClass3 || c.Cel.Rank == RankClass4) && - c.Season != Lent && c.Season != Passiontide - if ordinaryFeria { - p++ // an ordinary feria yields to an equal-class feast + yieldsToFeast := false + switch c.Cel.Rank { + case RankClass3, RankClass4: + yieldsToFeast = c.Season != Lent && c.Season != Passiontide + case RankClass2: + // A II-class Sunday (entry 15) wins; a II-class privileged feria -- + // Ember days, the late-Advent 17-23 Dec ferias (entry 18) -- yields + // to an equal-class feast (entry 16), e.g. St Matthew (21 Sep) + // beating the September Ember Wednesday, or St Thomas (21 Dec) + // beating an Advent late feria. + yieldsToFeast = !c.Sunday + } + if yieldsToFeast { + p++ } else { - p-- // Sundays, named feasts, and penitential ferias win their ties + p-- // Sundays, I-class ferias, and penitential (Lent/Passiontide) ferias win their ties } } else if c.Cel.Class == ClassLord && c.Cel.Rank == RankClass2 { // A II class feast of the Lord takes the place of a II class Sunday it // falls on (unlike a saint's feast, which is only commemorated). Give it // the edge over the Sunday's tie-break bonus. p -= 2 + } else if c.Cel.Rank == RankClass1 && beatsClass1Sunday(c.Cel.Slug) { + // RG 91 entries 4 (Immaculate Conception, Assumption BVM) and 5 + // (Vigil & Octave day of the Nativity) both sit ABOVE entry 6 + // (Sundays of Advent/Lent/Passiontide, Low Sunday) -- unlike an + // ORDINARY I-class feast (entry 11, e.g. St Joseph, the Precious + // Blood), which yields to a I-class Sunday, these win the tie. + // Found while verifying defect 4 (Sunday ranks): before that fix, + // Advent/Lent Sundays were wrongly II class, so these feasts beat + // them outright on base class alone, accidentally right; once + // Sundays became I class the tie-break mattered, and without this + // branch the Sunday would wrongly win. Two live cases in the fixed + // calendar: the Immaculate Conception (8 December) on an Advent + // Sunday, and the Vigil of Christmas (24 December) on Advent IV -- + // the latter is not merely a wrong winner but a WORSE bug without + // this branch: transferIfImpededEF has no way to re-place a + // transfer that crosses the Dec31/Jan1 boundary (celebrationDate + // re-resolves a fixed date using the YEAR OF THE DAY BEING QUERIED, + // so a walk landing in January of the following year can never + // match the query that produced it), so the Vigil simply vanished + // for the year instead of landing on the wrong day. The Assumption + // (15 August) never falls in Advent or Lent, so its own share of + // this branch is citation-complete but not live. + p -= 2 } return p } +// beatsClass1Sunday reports whether slug is one of RG 91's entries 4 or 5 -- +// the Immaculate Conception, the Assumption, or the Vigil of Christmas -- +// all of which sit above entry 6's Sundays in the Table of Precedence. +func beatsClass1Sunday(slug string) bool { + return strings.Contains(slug, "immaculate-conception") || + strings.Contains(slug, "assumption-of-the-blessed-virgin-mary") || + slug == "vigil-of-christmas" +} + // pickEF returns the observed EF celebration and the commemorations, ordered // deterministically by precedence then slug. func pickEF(cands []candidate) (candidate, []candidate) { diff --git a/internal/calendar/precedence_ef_repro_test.go b/internal/calendar/precedence_ef_repro_test.go new file mode 100644 index 0000000..11fd6ca --- /dev/null +++ b/internal/calendar/precedence_ef_repro_test.go @@ -0,0 +1,160 @@ +package calendar_test + +// Reproduction tests for three named EF precedence defects (colitur's +// differential/oracle audit against lectio's ~66-line EF precedence +// approximation, internal/calendar/precedence_ef.go). Each test fails before +// its fix and passes after -- see the report for the exact pre-fix failure +// message. These exercise the REAL tridentine sanctoral data +// (caldata.Tridentine()) through the public Compute entry point, since the +// bugs are about how real fixed-date feasts interact with the temporal +// calendar, not about precedenceEF's arithmetic in isolation (that is +// covered separately, package-internal, in precedence_ef_test.go). + +import ( + "testing" + "time" + + "github.com/lukaszkasprzak/lectio/internal/caldata" + "github.com/lukaszkasprzak/lectio/internal/calendar" +) + +func efCompute(date string) calendar.LiturgicalDay { + sel := calendar.DefaultSelection() + sel.Form = "old" + d, _ := time.Parse("2006-01-02", date) + return calendar.Compute(d.UTC(), sel, []calendar.Layer{caldata.Tridentine()}) +} + +// TestJosephYieldsToSundayOfLent: RG 91 entry 6 (Sundays of Lent, I class) +// vs entry 11 (I-class feasts of the universal Church not above) -- the +// Sunday holds; St Joseph (19 March) transfers to the next free day (RG 95, +// RG 96), landing on the 20th. Before the fix (defect 4: Sunday ranks), Lent +// Sundays were wrongly II class, so Joseph (I class) won outright every time +// this collision occurred. +func TestJosephYieldsToSundayOfLent(t *testing.T) { + for _, year := range []string{"2006", "2017", "2023", "2028", "2034", "2045"} { + sunday := efCompute(year + "-03-19") + if sunday.Observed.Slug == "joseph-spouse-of-the-bl-virgin-mary" { + t.Errorf("%s-03-19 observed = %q want the Lent Sunday (RG 91 entry 6 beats entry 11)", year, sunday.Observed.Slug) + } + next := efCompute(year + "-03-20") + if next.Observed.Slug != "joseph-spouse-of-the-bl-virgin-mary" { + t.Errorf("%s-03-20 observed = %q want joseph-spouse-of-the-bl-virgin-mary (transferred one day, RG 96)", year, next.Observed.Slug) + } + } +} + +// TestTransferSkipsBothIAndIIClass: RG 96 -- an impeded I-class feast +// transfers to the next day that is NOT ITSELF I OR II CLASS (not merely "not +// I class"). 2011: the Sacred Heart (Friday after the Corpus Christi octave) +// falls on 1 July and impedes the Precious Blood (also 1 July, fixed). 2 +// July is the Visitation (II class, fixed); 3 July is an ordinary II-class +// Sunday. Both must be skipped; the Precious Blood lands on 4 July, and the +// Visitation is observed, undisplaced, on its own day. +func TestTransferSkipsBothIAndIIClass(t *testing.T) { + if got := efCompute("2011-07-01").Observed.Slug; got != "ef-sacred-heart" { + t.Fatalf("2011-07-01 observed = %q want ef-sacred-heart", got) + } + if got := efCompute("2011-07-02").Observed.Slug; got != "visitation-of-the-blessed-virgin-mary" { + t.Errorf("2011-07-02 observed = %q want visitation-of-the-blessed-virgin-mary (RG 96: the Precious Blood must skip past it, not displace it)", got) + } + if got := efCompute("2011-07-03").Observed.Slug; got != "ef-time-after-pentecost-sunday-3" { + t.Errorf("2011-07-03 observed = %q want ef-time-after-pentecost-sunday-3 (an ordinary II-class Sunday also blocks a I-class transfer)", got) + } + if got := efCompute("2011-07-04").Observed.Slug; got != "precious-blood-of-our-lord-jesus-christ" { + t.Errorf("2011-07-04 observed = %q want precious-blood-of-our-lord-jesus-christ (RG 96: first day that is neither I nor II class)", got) + } +} + +// TestMatthewBeatsSeptemberEmberWednesday: RG 91 -- St Matthew (21 September, +// II class) and the September Ember Wednesday are both II class; the table +// decides the tie. Entry 16 (II-class feasts of the universal Church) sits +// ABOVE entry 18 (II-class ferias, including the Ember days) -- the feast +// wins, the Ember feria is only commemorated. +func TestMatthewBeatsSeptemberEmberWednesday(t *testing.T) { + // 21 September falls on the September Ember Wednesday whenever the third + // Sunday of September is the 18th -- 2016 and 2022 both qualify. + for _, date := range []string{"2016-09-21", "2022-09-21"} { + day := efCompute(date) + if day.Observed.Slug != "matthew" { + t.Errorf("%s observed = %q want matthew (RG 91 entry 16 beats entry 18)", date, day.Observed.Slug) + } + } +} + +// TestImmaculateConceptionBeatsAdventSunday: found, not named among the +// seven, while verifying defect 4 (Sunday ranks) against the real sanctoral +// data. RG 91 entry 4 (Immaculate Conception, Assumption BVM) sits ABOVE +// entry 6 (Sundays of Advent/Lent/Passiontide) -- unlike an ORDINARY +// I-class feast (entry 11, e.g. St Joseph), the Immaculate Conception +// (8 December) is not impeded by the Advent Sunday it falls on at all. Before +// defect 4's own fix, Advent Sundays were wrongly II class, so this was +// accidentally right (I class beats II class outright); once Sundays became +// I class the tie mattered for the first time. +func TestImmaculateConceptionBeatsAdventSunday(t *testing.T) { + for _, year := range []string{"2013", "2019", "2024"} { + day := efCompute(year + "-12-08") + if day.Observed.Slug != "immaculate-conception-of-the-blessed-virgin-mary" { + t.Errorf("%s-12-08 observed = %q want immaculate-conception-of-the-blessed-virgin-mary (RG 91 entry 4 beats entry 6)", year, day.Observed.Slug) + } + } +} + +// TestVigilOfChristmasSurvivesAdventSunday: found, not named among the +// seven, while verifying defect 4 against the real sanctoral data -- and +// worse than a wrong winner. RG 91 entry 5 (Vigil & Octave day of the +// Nativity) also sits above entry 6, so the Vigil of Christmas (24 December) +// is not impeded by falling on Advent IV either. Without this, defect 4 +// alone would have made the Advent Sunday win a genuine tie, sending the +// Vigil into transferIfImpededEF's forward walk -- which has no way to +// re-place a transfer that crosses the Dec31/Jan1 boundary (celebrationDate +// re-resolves a fixed date using the year of whatever day is being queried, +// so a walk landing in the following January can never match the query that +// produced it). The Vigil did not move to the wrong day; it vanished for the +// whole year. +func TestVigilOfChristmasSurvivesAdventSunday(t *testing.T) { + for _, year := range []string{"2006", "2017", "2023", "2028"} { + day := efCompute(year + "-12-24") + if day.Observed.Slug != "vigil-of-christmas" { + t.Errorf("%s-12-24 observed = %q want vigil-of-christmas (RG 91 entry 5 beats entry 6; must not vanish)", year, day.Observed.Slug) + } + } +} + +// TestPurificationBeatsFebruarySunday: the fixture behind classOf's own +// Purification decision (scripts/gen-sanctoral-ef.go), committed here rather +// than left as an assertion only, because the deciding years (2 February on +// a Sunday: 2014, 2020, 2025, 2031, 2042, 2048) fall entirely outside this +// repo's own missalemeum oracle snapshot (sources/snapshot.tar.gz, +// 2026-01-01 .. 2027-12-31), so nothing else in this repository can +// reproduce the evidence classOf's decision rests on. (2036, sometimes +// quoted alongside 2025/2031 as a third example: 2 February 2036 is in fact +// a SATURDAY, `date -d 2036-02-02 +%A` -- checked here rather than repeated; +// 2042 is the correct next instance after 2031.) +// +// RG 91 entry 14 ("Festa Domini II classis") sits above entry 15 +// ("Dominicae II classis"), which sits above entry 16 ("Festa II classis +// Ecclesiae universae, quae non [sunt Domini]") -- entry 14 takes an +// occurring Sunday's place outright, entry 16 is merely commemorated on +// one. The Purification (2 February) matches entry 14's pattern, not entry +// 16's, independently fetched live from missalemeum for five different +// Sundays: 2014-02-02, 2020-02-02, 2025-02-02, 2031-02-02, 2042-02-02 (all +// "id":"sancti:02-02:2:w", "commemorations":[]). Control: +// nativity-of-the-blessed-virgin-mary (8 September, an undisputed ordinary +// Marian feast, entry 16's own pattern) on a Sunday -- 2019-09-08 -- shows +// the SUNDAY observed, the feast commemorated instead: the opposite shape, +// proving the Purification's own treatment is a deliberate pattern in the +// oracle, not a gap. This is a decision AGAINST the calendarium's own title +// ("IN PURIFICATIONE B. MARIAE VIRG.") and RG 120(b) (which files 2 +// February under the white-colour rule's "B. Mariae Virg." heading, kept +// separate from 120(a)'s "Domini" heading) -- both point BVM; the +// occurrence-behaviour evidence here points Domini. See classOf's own doc +// comment for the fuller account; not re-argued here. +func TestPurificationBeatsFebruarySunday(t *testing.T) { + for _, year := range []string{"2014", "2020", "2025", "2031", "2042"} { + day := efCompute(year + "-02-02") + if day.Observed.Slug != "purification-of-the-blessed-virgin-mary" { + t.Errorf("%s-02-02 observed = %q want purification-of-the-blessed-virgin-mary (RG 91 entry 14 beats entry 15)", year, day.Observed.Slug) + } + } +} diff --git a/internal/calendar/precedence_ef_test.go b/internal/calendar/precedence_ef_test.go index 818b452..d5e254f 100644 --- a/internal/calendar/precedence_ef_test.go +++ b/internal/calendar/precedence_ef_test.go @@ -6,6 +6,14 @@ func efCand(rank Rank, temporal bool) candidate { return candidate{Cel: Celebration{Rank: rank}, Temporal: temporal} } +// efTemporalCand builds a temporal candidate with the season/Sunday flags +// precedenceEF's tie-break actually reads, so a test claiming to exercise +// "a Sunday" or "a Lenten feria" genuinely sets those fields rather than +// happening to pass for an unrelated reason (e.g. a class difference alone). +func efTemporalCand(rank Rank, season Season, sunday bool) candidate { + return candidate{Cel: Celebration{Rank: rank}, Temporal: true, Season: season, Sunday: sunday} +} + func TestPrecedenceEF(t *testing.T) { c1 := efCand(RankClass1, false) c3 := efCand(RankClass3, false) @@ -14,16 +22,57 @@ func TestPrecedenceEF(t *testing.T) { if !(precedenceEF(c1) < precedenceEF(c3) && precedenceEF(c3) < precedenceEF(c4) && precedenceEF(c4) < precedenceEF(comm)) { t.Error("EF class ordering broken (class-1 > class-3 > class-4 > commemoration)") } - // at equal class, the temporal office wins. - temp := efCand(RankClass2, true) + // a I-class feast beats a II-class Sunday (RG 91 entry 11 vs entry 15 -- + // different classes, so this holds regardless of the tie-break, but the + // candidate is still marked Sunday so the test means what its name says). + sunday2 := efTemporalCand(RankClass2, TimeAfterPentecost, true) + feast1 := efCand(RankClass1, false) + obs, others := pickEF([]candidate{sunday2, feast1}) + if obs.Cel.Rank != RankClass1 || len(others) != 1 { + t.Errorf("I-class feast should win over II-class Sunday, got %+v", obs.Cel) + } +} + +// TestPrecedenceEFClass2SundayVsFeria: RG 91 entries 15/16/18 -- at class 2, +// a SUNDAY wins its tie against an equal-class feast (entry 15 above 16), but +// a privileged FERIA (the Ember days, the late-Advent 17-23 Dec ferias, entry +// 18) YIELDS to one (entry 16 above 18) -- the opposite of the Sunday case. +// This is defect 2's own witness: before the fix, precedenceEF treated every +// non-ordinaryFeria temporal candidate the same way, so an Ember/late-Advent +// feria wrongly won its tie exactly like a Sunday does. +func TestPrecedenceEFClass2SundayVsFeria(t *testing.T) { saint := efCand(RankClass2, false) - obs, _ := pickEF([]candidate{saint, temp}) - if !obs.Temporal { - t.Error("equal-class: temporal office should be observed") + + sunday := efTemporalCand(RankClass2, TimeAfterPentecost, true) + obsSunday, _ := pickEF([]candidate{saint, sunday}) + if !obsSunday.Temporal { + t.Errorf("a II-class Sunday should win its tie against an equal-class feast, got %+v observed", obsSunday.Cel) } - // a I-class feast beats a II-class Sunday. - obs2, others := pickEF([]candidate{efCand(RankClass2, true), efCand(RankClass1, false)}) - if obs2.Cel.Rank != RankClass1 || len(others) != 1 { - t.Errorf("I-class feast should win over II-class Sunday, got %+v", obs2.Cel) + + emberFeria := efTemporalCand(RankClass2, TimeAfterPentecost, false) // e.g. the September Ember Wednesday + obsFeria, _ := pickEF([]candidate{saint, emberFeria}) + if obsFeria.Temporal { + t.Errorf("a II-class privileged feria should yield its tie to an equal-class feast, got %+v observed (temporal)", obsFeria.Cel) + } +} + +// TestPrecedenceEFClass3FeriaSeason: the pre-existing rule (unchanged by +// defect 2's fix), stated explicitly rather than left implicit: an ORDINARY +// III/IV-class feria (per annum, Advent to 16 Dec, Septuagesima) yields to an +// equal-class feast; the ferias of Lent and Passiontide are privileged and +// win instead. +func TestPrecedenceEFClass3FeriaSeason(t *testing.T) { + saint := efCand(RankClass3, false) + + ordinary := efTemporalCand(RankClass3, Advent, false) + obsOrdinary, _ := pickEF([]candidate{saint, ordinary}) + if obsOrdinary.Temporal { + t.Errorf("an ordinary Advent feria should yield to an equal-class feast, got %+v observed (temporal)", obsOrdinary.Cel) + } + + lenten := efTemporalCand(RankClass3, Lent, false) + obsLenten, _ := pickEF([]candidate{saint, lenten}) + if !obsLenten.Temporal { + t.Errorf("a Lenten feria should win its tie against an equal-class feast, got %+v observed", obsLenten.Cel) } } diff --git a/internal/calendar/temporal_ef.go b/internal/calendar/temporal_ef.go index 7420ebd..c649405 100644 --- a/internal/calendar/temporal_ef.go +++ b/internal/calendar/temporal_ef.go @@ -74,6 +74,16 @@ func efCel(season Season, slug string, col Colour, rank Rank, week int) temporal } } +// efSunday is efCel plus the Sunday flag, for the temporal candidates that +// are actual Sundays -- precedenceEF's tie-break needs to tell a Sunday (RG +// 91 entry 15, wins its tie) apart from an equal-class privileged FERIA +// (entry 18, the Ember/late-Advent days, which yields). +func efSunday(season Season, slug string, col Colour, rank Rank, week int) temporalDay { + day := efCel(season, slug, col, rank, week) + day.Sunday = true + return day +} + // temporalEF computes the 1962 temporal identity of date. Season is exact // (oracle-validated); ranks/weeks are best-effort for display. func temporalEF(date time.Time) temporalDay { @@ -87,6 +97,15 @@ func temporalEF(date time.Time) temporalDay { if !date.Before(easter.AddDate(0, 0, 50)) && !date.After(easter.AddDate(0, 0, 55)) { col = Red } + // Holy Thursday (the Mass of Chrism and the Mass in Cena Domini) is white, + // a whole-Mass exception to Passiontide's violet -- RG 128(b)'s own named + // exception list, and RG 122 stating the same fact affirmatively in the + // White section. Good Friday and Holy Saturday, either side, are NOT + // exceptions here (RG 132's black for Good Friday's liturgical action is a + // separate, unmodelled gap -- see precedence_ef.go's doc comments). + if sameDay(date, easter.AddDate(0, 0, -3)) { + col = White + } sun := date.Weekday() == time.Sunday // Major feasts of the Lord (I class): nice titles + colour. @@ -129,8 +148,20 @@ func temporalEF(date time.Time) temporalDay { if sun { week := efWeek(date, season, y, easter) rank := RankClass2 - if season == Advent && sameDay(date, adventStart(y)) { - rank = RankClass1 // 1st Sunday of Advent + sundayColour := col + if season == Advent || season == Lent { + // RG 11-12 / RG 91 entry 6: every Sunday of Advent and every Sunday + // of Lent is I class -- not only Advent I, the sole case previously + // handled (Passiontide's own two Sundays, Passion and Palm, are + // already I class via the named-feast switch above; Low Sunday + // likewise). + rank = RankClass1 + switch { + case season == Advent && week == 3: + sundayColour = Rose // Gaudete -- RG 131, that Sunday's Office/Mass only + case season == Lent && week == 4: + sundayColour = Rose // Laetare -- RG 131, that Sunday's Office/Mass only + } } // Resumed Sundays after Pentecost (1960 Rubrics): when Easter is early // there are more than 24 Sundays after Pentecost. The LAST Sunday before @@ -140,17 +171,17 @@ func temporalEF(date time.Time) temporalDay { if season == TimeAfterPentecost { lastSun := adventStart(y).AddDate(0, 0, -7) if sameDay(date, lastSun) { - return efCel(TimeAfterPentecost, "ef-time-after-pentecost-sunday-24", col, rank, 24) + return efSunday(TimeAfterPentecost, "ef-time-after-pentecost-sunday-24", col, rank, 24) } if week > 23 { p := daysBetween(easter.AddDate(0, 0, 49), lastSun) / 7 // total Sundays after Pentecost e := week - p + 7 // resumed Sunday after Epiphany // Season stays time-after-pentecost (calendrical); the Epiphany // slug only routes the readings to the resumed Mass. - return efCel(TimeAfterPentecost, "ef-time-after-epiphany-sunday-"+strconv.Itoa(e), Green, rank, e) + return efSunday(TimeAfterPentecost, "ef-time-after-epiphany-sunday-"+strconv.Itoa(e), Green, rank, e) } } - return efCel(season, "ef-"+string(season)+"-sunday-"+strconv.Itoa(week), col, rank, week) + return efSunday(season, "ef-"+string(season)+"-sunday-"+strconv.Itoa(week), sundayColour, rank, week) } // The days between Ash Wednesday and the 1st Sunday of Lent have their own // proper Masses (not part of a numbered Lenten week). @@ -166,6 +197,17 @@ func temporalEF(date time.Time) temporalDay { // saint (e.g. the Conversion of St Paul, Jan 25) displaces them. rank = RankClass3 } + if season == Advent && date.Month() == time.December && date.Day() >= 17 && date.Day() <= 23 { + // RG 91 entry 18: the late-Advent ferias (17-23 Dec) are II class + // privileged ferias, not the ordinary III class of the rest of Advent. + rank = RankClass2 + } + if season == Christmas && date.Month() == time.December && date.Day() >= 26 { + // RG 67/68: "Dies infra octavam sunt II classis" -- days within the + // Octave of the Nativity (26-31 Dec) are II class; the octave day + // itself (1 Jan) is I class, already handled above as a named feast. + rank = RankClass2 + } if efPrivilegedFeria(date, easter) { // The days of Holy Week and the privileged octaves of Easter and // Pentecost are I class; no saint's feast is admitted (the feast is @@ -173,12 +215,11 @@ func temporalEF(date time.Time) temporalDay { // the temporal office win, matching the 1962 occurrence rules. rank = RankClass1 } - // The Ember Days of September and Advent (Wednesday, Friday, Saturday after - // the third Sunday of the month/season) are II class privileged ferias in - // violet; they displace a III class saint (only commemorated). The Lenten - // Ember days are already III class Lenten ferias, and the Whitsun Ember days - // fall inside the I class Pentecost octave handled above. - if es, ok := efEmberSlug(date, y); ok { + // The Ember Days of September, Advent and Lent (Wednesday, Friday, Saturday + // after the anchor Sunday) are II class privileged ferias in violet; they + // displace a III class saint (only commemorated) -- RG 91 entry 18. The + // Whitsun Ember days fall inside the I class Pentecost octave handled above. + if es, ok := efEmberSlug(date, y, easter); ok { return efCel(season, es, Violet, RankClass2, week) } // Unique ferial slug (season-week-weekday) so proper ferias (Lent, Advent, @@ -197,22 +238,26 @@ func thirdSundayOfSeptember(y int) time.Time { } // efEmberSlug returns the Ember-day slug for date, if it is an Ember Wednesday, -// Friday or Saturday of September or Advent (the day after the third Sunday + -// 3/5/6). Returns ("", false) otherwise. -func efEmberSlug(date time.Time, y int) (string, bool) { +// Friday or Saturday of September, Advent or Lent (the day after the anchor +// Sunday + 3/5/6: the third Sunday of September, Advent III, or Lent I -- +// MR1962, "De anno et eius partibus", Quatuor Tempora). Returns ("", false) +// otherwise. The Whitsun Ember days are not listed here: they fall inside the +// I class Pentecost octave, handled separately by efPrivilegedFeria. +func efEmberSlug(date time.Time, y int, easter time.Time) (string, bool) { for _, e := range []struct { - third time.Time + anchor time.Time season string }{ {thirdSundayOfSeptember(y), "september"}, {adventStart(y).AddDate(0, 0, 14), "advent"}, // 3rd Sunday of Advent + {easter.AddDate(0, 0, -42), "lent"}, // 1st Sunday of Lent } { switch { - case sameDay(date, e.third.AddDate(0, 0, 3)): + case sameDay(date, e.anchor.AddDate(0, 0, 3)): return "ef-" + e.season + "-ember-wed", true - case sameDay(date, e.third.AddDate(0, 0, 5)): + case sameDay(date, e.anchor.AddDate(0, 0, 5)): return "ef-" + e.season + "-ember-fri", true - case sameDay(date, e.third.AddDate(0, 0, 6)): + case sameDay(date, e.anchor.AddDate(0, 0, 6)): return "ef-" + e.season + "-ember-sat", true } } 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) + } + } +} diff --git a/internal/calendar/testdata/oracle-ef.json b/internal/calendar/testdata/oracle-ef.json index 3ddf10c..f857288 100644 --- a/internal/calendar/testdata/oracle-ef.json +++ b/internal/calendar/testdata/oracle-ef.json @@ -1,4382 +1,6586 @@ { - "2025-01-01": { + "2026-01-01": { + "id": "sancti:01-01:1:w", "tempora": "", "title": "Octave Day of Christmas", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-06": { + "2026-01-02": { + "id": "sancti:01-01:1:w", "tempora": "", - "title": "Epiphany of the Lord", - "rank": 1, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-01-10": { + "2026-01-03": { + "id": "commune:C10b:4:w", "tempora": "", - "title": "Feria", + "title": "II Mass of the B. V. M. – Vultum Tuum", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-07": { + "2026-01-04": { + "id": "tempora:Nat2-0:2:w", + "tempora": "", + "title": "Holy Name of Jesus", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-01-05": { + "id": "sancti:01-01:1:w", "tempora": "", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-02": { + "2026-01-06": { + "id": "sancti:01-06:1:w", + "tempora": "", + "title": "Epiphany of the Lord", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-01-07": { + "id": "sancti:01-06:1:w", "tempora": "", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-03": { + "2026-01-08": { + "id": "sancti:01-06:1:w", "tempora": "", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-05": { + "2026-01-09": { + "id": "sancti:01-06:1:w", "tempora": "", - "title": "Holy Name of Jesus", - "rank": 2, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-01-09": { + "2026-01-10": { + "id": "commune:C10b:4:w", "tempora": "", - "title": "Feria", + "title": "II Mass of the B. V. M. – Vultum Tuum", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-12": { + "2026-01-11": { + "id": "tempora:Epi1-0:2:w", "tempora": "", "title": "The Holy Family: Jesus, Mary & Joseph", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-20": { - "tempora": "Feria II after II Sunday after Epiphany", - "title": "Sts. Fabian & Sebastian", - "rank": 3, - "colour": "r" - }, - "2025-01-16": { - "tempora": "Feria V after Epiphany", - "title": "St. Marcellus I", - "rank": 3, - "colour": "r" - }, - "2025-01-04": { - "tempora": "", - "title": "II Mass of the B. V. M. – Vultum Tuum", + "2026-01-12": { + "id": "tempora:Epi1-0a:2:w", + "tempora": "Feria II after Epiphany", + "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-13": { - "tempora": "Feria II after Epiphany", + "2026-01-13": { + "id": "sancti:01-13:2:w", + "tempora": "Feria III after Epiphany", "title": "Commemoration of the Baptism of the Lord", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-19": { - "tempora": "", - "title": "II Sunday after Epiphany", - "rank": 2, - "colour": "g" + "2026-01-14": { + "id": "sancti:01-14:3:w", + "tempora": "Feria IV after Epiphany", + "title": "St. Hilary", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-01-08": { - "tempora": "", - "title": "Feria", - "rank": 4, - "colour": "w" + "2026-01-15": { + "id": "sancti:01-15:3:w", + "tempora": "Feria V after Epiphany", + "title": "St. Paul, the First Hermit", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-01-17": { + "2026-01-16": { + "id": "sancti:01-16:3:r", "tempora": "Feria VI after Epiphany", + "title": "St. Marcellus I", + "rank": 3, + "colours": [ + "r" + ] + }, + "2026-01-17": { + "id": "sancti:01-17:3:w", + "tempora": "Saturday after Epiphany", "title": "St. Anthony", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-26": { + "2026-01-18": { + "id": "tempora:Epi2-0:2:g", "tempora": "", - "title": "III Sunday after Epiphany", + "title": "II Sunday after Epiphany", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-01-25": { - "tempora": "Saturday after II Sunday after Epiphany", - "title": "Conversion of St. Paul", - "rank": 3, - "colour": "w" - }, - "2025-01-11": { - "tempora": "", - "title": "II Mass of the B. V. M. – Vultum Tuum", + "2026-01-19": { + "id": "tempora:Epi2-0:2:g", + "tempora": "Feria II after II Sunday after Epiphany", + "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "g" + ] }, - "2025-01-21": { + "2026-01-20": { + "id": "sancti:01-20:3:r", "tempora": "Feria III after II Sunday after Epiphany", - "title": "St. Agnes", - "rank": 3, - "colour": "r" - }, - "2025-01-27": { - "tempora": "Feria II after III Sunday after Epiphany", - "title": "St. John Chrysostom", + "title": "Sts. Fabian & Sebastian", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-01-22": { + "2026-01-21": { + "id": "sancti:01-21:3:r", "tempora": "Feria IV after II Sunday after Epiphany", - "title": "Sts. Vincent & Anastasius", - "rank": 3, - "colour": "r" - }, - "2025-01-14": { - "tempora": "Feria III after Epiphany", - "title": "St. Hilary", - "rank": 3, - "colour": "w" - }, - "2025-01-31": { - "tempora": "Feria VI after III Sunday after Epiphany", - "title": "St. John Bosco", + "title": "St. Agnes", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-01-15": { - "tempora": "Feria IV after Epiphany", - "title": "St. Paul, the First Hermit", + "2026-01-22": { + "id": "sancti:01-22:3:r", + "tempora": "Feria V after II Sunday after Epiphany", + "title": "Sts. Vincent & Anastasius", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-01-28": { - "tempora": "Feria III after III Sunday after Epiphany", - "title": "St. Peter Nolasco", + "2026-01-23": { + "id": "sancti:01-23:3:w", + "tempora": "Feria VI after II Sunday after Epiphany", + "title": "St. Raymond of Peñafort", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-01-24": { - "tempora": "Feria VI after II Sunday after Epiphany", + "2026-01-24": { + "id": "sancti:01-24:3:r", + "tempora": "Saturday after II Sunday after Epiphany", "title": "St. Timothy", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-01-18": { - "tempora": "Saturday after Epiphany", - "title": "II Mass of the B. V. M. – Vultum Tuum", - "rank": 4, - "colour": "w" + "2026-01-25": { + "id": "tempora:Epi3-0:2:g", + "tempora": "", + "title": "III Sunday after Epiphany", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-02-01": { - "tempora": "Saturday after III Sunday after Epiphany", - "title": "St. Ignatius of Antioch", + "2026-01-26": { + "id": "sancti:01-26:3:r", + "tempora": "Feria II after III Sunday after Epiphany", + "title": "St. Polycarp", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-01-29": { - "tempora": "Feria IV after III Sunday after Epiphany", - "title": "St. Francis de Sales", + "2026-01-27": { + "id": "sancti:01-27:3:w", + "tempora": "Feria III after III Sunday after Epiphany", + "title": "St. John Chrysostom", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-05": { - "tempora": "Feria IV after IV Sunday after Epiphany", - "title": "St. Agatha", + "2026-01-28": { + "id": "sancti:01-28:3:w", + "tempora": "Feria IV after III Sunday after Epiphany", + "title": "St. Peter Nolasco", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-02-09": { - "tempora": "", - "title": "V Sunday after Epiphany", - "rank": 2, - "colour": "g" - }, - "2025-02-03": { - "tempora": "Feria II after IV Sunday after Epiphany", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2025-02-07": { - "tempora": "Feria VI after IV Sunday after Epiphany", - "title": "St. Romuald", + "2026-01-29": { + "id": "sancti:01-29:3:w", + "tempora": "Feria V after III Sunday after Epiphany", + "title": "St. Francis de Sales", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-10": { - "tempora": "Feria II after V Sunday after Epiphany", - "title": "St. Scholastica", + "2026-01-30": { + "id": "sancti:01-30:3:r", + "tempora": "Feria VI after III Sunday after Epiphany", + "title": "St. Martina", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-02-11": { - "tempora": "Feria III after V Sunday after Epiphany", - "title": "Our Lady of Lourdes", + "2026-01-31": { + "id": "sancti:01-31:3:w", + "tempora": "Saturday after III Sunday after Epiphany", + "title": "St. John Bosco", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-16": { + "2026-02-01": { + "id": "tempora:Quadp1-0:2:v", "tempora": "", "title": "Septuagesima Sunday", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-02-13": { - "tempora": "Feria V after V Sunday after Epiphany", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2025-02-02": { - "tempora": "IV Sunday after Epiphany", + "2026-02-02": { + "id": "sancti:02-02:2:w", + "tempora": "Feria II after Septuagesima", "title": "Purification of the Blessed Virgin Mary", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-12": { - "tempora": "Feria IV after V Sunday after Epiphany", - "title": "Seven Holy Servite Founders", - "rank": 3, - "colour": "w" + "2026-02-03": { + "id": "tempora:Quadp1-0:2:v", + "tempora": "Feria III after Septuagesima", + "title": "Feria", + "rank": 4, + "colours": [ + "v" + ] }, - "2025-02-04": { - "tempora": "Feria III after IV Sunday after Epiphany", + "2026-02-04": { + "id": "sancti:02-04:3:w", + "tempora": "Feria IV after Septuagesima", "title": "St. Andrew Corsini", "rank": 3, - "colour": "w" - }, - "2025-01-30": { - "tempora": "Feria V after III Sunday after Epiphany", - "title": "St. Martina", - "rank": 3, - "colour": "r" - }, - "2025-01-23": { - "tempora": "Feria V after II Sunday after Epiphany", - "title": "St. Raymond of Peñafort", - "rank": 3, - "colour": "w" - }, - "2025-02-17": { - "tempora": "Feria II after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" + "colours": [ + "w" + ] }, - "2025-02-20": { + "2026-02-05": { + "id": "sancti:02-05:3:r", "tempora": "Feria V after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" - }, - "2025-02-19": { - "tempora": "Feria IV after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" + "title": "St. Agatha", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-02-21": { + "2026-02-06": { + "id": "sancti:02-06:3:w", "tempora": "Feria VI after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" + "title": "St. Titus", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-02-14": { - "tempora": "Feria VI after V Sunday after Epiphany", - "title": "Feria", - "rank": 4, - "colour": "g" + "2026-02-07": { + "id": "sancti:02-07:3:w", + "tempora": "Saturday after Septuagesima", + "title": "St. Romuald", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-02-23": { + "2026-02-08": { + "id": "tempora:Quadp2-0:2:v", "tempora": "", "title": "Sexagesima Sunday", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-02-08": { - "tempora": "Saturday after IV Sunday after Epiphany", - "title": "St. John of Matha", - "rank": 3, - "colour": "w" - }, - "2025-02-06": { - "tempora": "Feria V after IV Sunday after Epiphany", - "title": "St. Titus", + "2026-02-09": { + "id": "sancti:02-09:3:w", + "tempora": "Feria II after Sexagesima", + "title": "St. Cyril of Alexandria", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-25": { + "2026-02-10": { + "id": "sancti:02-10:3:w", "tempora": "Feria III after Sexagesimæ", - "title": "Feria", - "rank": 4, - "colour": "v" - }, - "2025-03-05": { - "tempora": "", - "title": "Ash Wednesday", - "rank": 1, - "colour": "v" - }, - "2025-02-24": { - "tempora": "Feria II after Sexagesima", - "title": "St. Matthias", - "rank": 2, - "colour": "r" + "title": "St. Scholastica", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-02-26": { + "2026-02-11": { + "id": "sancti:02-11:3:w", "tempora": "Feria IV after Sexagesimæ", - "title": "Feria", - "rank": 4, - "colour": "v" + "title": "Our Lady of Lourdes", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-02-27": { + "2026-02-12": { + "id": "sancti:02-12:3:w", "tempora": "Feria V after Sexagesimæ", - "title": "St. Gabriel of Our Lady of Sorrows", + "title": "Seven Holy Servite Founders", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-02-28": { + "2026-02-13": { + "id": "tempora:Quadp2-0:2:v", "tempora": "Feria VI after Sexagesimæ", "title": "Feria", "rank": 4, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-02-22": { - "tempora": "Saturday after Septuagesima", - "title": "Chair of St. Peter", + "2026-02-14": { + "id": "commune:C10c:4:w", + "tempora": "Saturday after Sexagesimæ", + "title": "III Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2026-02-15": { + "id": "tempora:Quadp3-0:2:v", + "tempora": "", + "title": "Quinquagesima Sunday", "rank": 2, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-03-03": { + "2026-02-16": { + "id": "tempora:Quadp3-0:2:v", "tempora": "Feria II after Quinquagesima", "title": "Feria", "rank": 4, - "colour": "v" + "colours": [ + "v" + ] + }, + "2026-02-17": { + "id": "tempora:Quadp3-0:2:v", + "tempora": "Feria III after Quinquagesima", + "title": "Feria", + "rank": 4, + "colours": [ + "v" + ] }, - "2025-03-02": { + "2026-02-18": { + "id": "tempora:Quadp3-3:1:v", "tempora": "", - "title": "Quinquagesima Sunday", - "rank": 2, - "colour": "v" + "title": "Ash Wednesday", + "rank": 1, + "colours": [ + "v" + ] }, - "2025-03-13": { + "2026-02-19": { + "id": "tempora:Quadp3-4:3:v", "tempora": "", - "title": "Feria V after the I Sunday of Lent", + "title": "Feria V after Ash Wednesday", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-11": { + "2026-02-20": { + "id": "tempora:Quadp3-5:3:v", "tempora": "", - "title": "Feria III after the I Sunday of Lent", + "title": "Feria VI after Ash Wednesday", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-09": { + "2026-02-21": { + "id": "tempora:Quadp3-6:3:v", + "tempora": "", + "title": "Saturday after Ash Wednesday", + "rank": 3, + "colours": [ + "v" + ] + }, + "2026-02-22": { + "id": "tempora:Quad1-0:1:v", "tempora": "", "title": "I Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-06": { + "2026-02-23": { + "id": "tempora:Quad1-1:3:v", "tempora": "", - "title": "Feria V after Ash Wednesday", + "title": "Feria II after the I Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-02-15": { - "tempora": "Saturday after V Sunday after Epiphany", - "title": "III Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2026-02-24": { + "id": "sancti:02-24:2:r", + "tempora": "Feria III after the I Sunday of Lent", + "title": "St. Matthias", + "rank": 2, + "colours": [ + "r" + ] }, - "2025-02-18": { - "tempora": "Feria III after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" + "2026-02-25": { + "id": "tempora:Quad1-3:2:v", + "tempora": "", + "title": "Ember Wednesday of Lent", + "rank": 2, + "colours": [ + "v" + ] + }, + "2026-02-26": { + "id": "tempora:Quad1-4:3:v", + "tempora": "", + "title": "Feria V after the I Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2025-03-14": { + "2026-02-27": { + "id": "tempora:Quad1-5:2:v", "tempora": "", "title": "Ember Friday of Lent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-16": { + "2026-02-28": { + "id": "tempora:Quad1-6:2:v", + "tempora": "", + "title": "Ember Saturday of Lent", + "rank": 2, + "colours": [ + "v" + ] + }, + "2026-03-01": { + "id": "tempora:Quad2-0:1:v", "tempora": "", "title": "II Sunday of Lent", "rank": 1, - "colour": "v" - }, - "2025-03-01": { - "tempora": "Saturday after Sexagesimæ", - "title": "III Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-03-12": { + "2026-03-02": { + "id": "tempora:Quad2-1:3:v", "tempora": "", - "title": "Ember Wednesday of Lent", - "rank": 2, - "colour": "v" + "title": "Feria II after the II Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2025-03-07": { + "2026-03-03": { + "id": "tempora:Quad2-2:3:v", "tempora": "", - "title": "Feria VI after Ash Wednesday", + "title": "Feria III after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-10": { + "2026-03-04": { + "id": "tempora:Quad2-3:3:v", "tempora": "", - "title": "Feria II after the I Sunday of Lent", + "title": "Feria IV after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-20": { + "2026-03-05": { + "id": "tempora:Quad2-4:3:v", "tempora": "", "title": "Feria V after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-04": { - "tempora": "Feria III after Quinquagesima", - "title": "St. Casimir", + "2026-03-06": { + "id": "tempora:Quad2-5:3:v", + "tempora": "", + "title": "Feria VI after the II Sunday of Lent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-03-22": { + "2026-03-07": { + "id": "tempora:Quad2-6:3:v", "tempora": "", "title": "Saturday after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-23": { + "2026-03-08": { + "id": "tempora:Quad3-0:1:v", "tempora": "", "title": "III Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-08": { + "2026-03-09": { + "id": "tempora:Quad3-1:3:v", "tempora": "", - "title": "Saturday after Ash Wednesday", + "title": "Feria II after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-26": { + "2026-03-10": { + "id": "tempora:Quad3-2:3:v", "tempora": "", - "title": "Feria IV after the III Sunday of Lent", + "title": "Feria III after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-30": { + "2026-03-11": { + "id": "tempora:Quad3-3:3:v", "tempora": "", - "title": "IV Sunday of Lent", - "rank": 1, - "colour": "pv" + "title": "Feria IV after the III Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2025-03-18": { + "2026-03-12": { + "id": "tempora:Quad3-4:3:v", "tempora": "", - "title": "Feria III after the II Sunday of Lent", + "title": "Feria V after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-19": { - "tempora": "Feria IV after the II Sunday of Lent", - "title": "St. Joseph, Spouse of the Bl. Virgin Mary", - "rank": 1, - "colour": "w" - }, - "2025-03-15": { + "2026-03-13": { + "id": "tempora:Quad3-5:3:v", "tempora": "", - "title": "Ember Saturday of Lent", - "rank": 2, - "colour": "v" + "title": "Feria VI after the III Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2025-03-29": { + "2026-03-14": { + "id": "tempora:Quad3-6:3:v", "tempora": "", "title": "Saturday after the III Sunday of Lent", "rank": 3, - "colour": "v" - }, - "2025-03-25": { - "tempora": "Feria III after the III Sunday of Lent", - "title": "Annunciation of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-04-06": { + "2026-03-15": { + "id": "tempora:Quad4-0:1:pv", "tempora": "", - "title": "Passion Sunday", + "title": "IV Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "p", + "v" + ] }, - "2025-03-31": { + "2026-03-16": { + "id": "tempora:Quad4-1:3:v", "tempora": "", "title": "Feria II after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-01": { + "2026-03-17": { + "id": "tempora:Quad4-2:3:v", "tempora": "", "title": "Feria III after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-28": { + "2026-03-18": { + "id": "tempora:Quad4-3:3:v", "tempora": "", - "title": "Feria VI after the III Sunday of Lent", + "title": "Feria IV after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-03-24": { - "tempora": "", - "title": "Feria II after the III Sunday of Lent", - "rank": 3, - "colour": "v" + "2026-03-19": { + "id": "sancti:03-19:1:w", + "tempora": "Feria V after the IV Sunday of Lent", + "title": "St. Joseph, Spouse of the Bl. Virgin Mary", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-03-21": { + "2026-03-20": { + "id": "tempora:Quad4-5:3:v", "tempora": "", - "title": "Feria VI after the II Sunday of Lent", + "title": "Feria VI after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-03": { + "2026-03-21": { + "id": "tempora:Quad4-6:3:v", "tempora": "", - "title": "Feria V after the IV Sunday of Lent", + "title": "Saturday after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-13": { + "2026-03-22": { + "id": "tempora:Quad5-0:1:v", "tempora": "", - "title": "Palm Sunday", + "title": "Passion Sunday", "rank": 1, - "colour": "rv" + "colours": [ + "v" + ] }, - "2025-03-27": { + "2026-03-23": { + "id": "tempora:Quad5-1:3:v", "tempora": "", - "title": "Feria V after the III Sunday of Lent", + "title": "Feria II of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-08": { + "2026-03-24": { + "id": "tempora:Quad5-2:3:v", "tempora": "", "title": "Feria III of Passion Week", "rank": 3, - "colour": "v" - }, - "2025-03-17": { - "tempora": "", - "title": "Feria II after the II Sunday of Lent", - "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-12": { - "tempora": "", - "title": "Saturday of Passion Week", - "rank": 3, - "colour": "v" + "2026-03-25": { + "id": "sancti:03-25:1:w", + "tempora": "Feria IV of Passion Week", + "title": "Annunciation of the Blessed Virgin Mary", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-04-10": { + "2026-03-26": { + "id": "tempora:Quad5-4:3:v", "tempora": "", "title": "Feria V of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-07": { + "2026-03-27": { + "id": "tempora:Quad5-5Feria:3:v", "tempora": "", - "title": "Feria II of Passion Week", + "title": "Feria VI of Passion Week", "rank": 3, - "colour": "v" - }, - "2025-04-20": { - "tempora": "", - "title": "Easter Sunday", - "rank": 1, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-04-09": { + "2026-03-28": { + "id": "tempora:Quad5-6:3:v", "tempora": "", - "title": "Feria IV of Passion Week", + "title": "Saturday of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-17": { + "2026-03-29": { + "id": "tempora:Quad6-0r:1:rv", "tempora": "", - "title": "Holy Thursday", + "title": "Palm Sunday", "rank": 1, - "colour": "w" + "colours": [ + "r", + "v" + ] }, - "2025-04-14": { + "2026-03-30": { + "id": "tempora:Quad6-1:1:v", "tempora": "", "title": "Feria II of Holy Week", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-04-02": { + "2026-03-31": { + "id": "tempora:Quad6-2:1:v", "tempora": "", - "title": "Feria IV after the IV Sunday of Lent", - "rank": 3, - "colour": "v" + "title": "Feria III of Holy Week", + "rank": 1, + "colours": [ + "v" + ] }, - "2025-04-11": { + "2026-04-01": { + "id": "tempora:Quad6-3:1:v", "tempora": "", - "title": "Feria VI of Passion Week", - "rank": 3, - "colour": "v" + "title": "Feria IV of Holy Week", + "rank": 1, + "colours": [ + "v" + ] }, - "2025-04-22": { + "2026-04-02": { + "id": "tempora:Quad6-4r:1:w", "tempora": "", - "title": "Tuesday in the Octave of Easter", + "title": "Holy Thursday", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-18": { + "2026-04-03": { + "id": "tempora:Quad6-5r:1:bv", "tempora": "", "title": "Good Friday", "rank": 1, - "colour": "bv" + "colours": [ + "b", + "v" + ] }, - "2025-04-27": { + "2026-04-04": { + "id": "tempora:Quad6-6r:1:vw", "tempora": "", - "title": "Low Sunday", + "title": "Holy Saturday", "rank": 1, - "colour": "w" + "colours": [ + "v", + "w" + ] }, - "2025-04-25": { + "2026-04-05": { + "id": "tempora:Pasc0-0:1:w", "tempora": "", - "title": "Friday in the Octave of Easter", + "title": "Easter Sunday", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-19": { + "2026-04-06": { + "id": "tempora:Pasc0-1:1:w", "tempora": "", - "title": "Holy Saturday", + "title": "Monday in the Octave of Easter", "rank": 1, - "colour": "vw" + "colours": [ + "w" + ] }, - "2025-04-23": { + "2026-04-07": { + "id": "tempora:Pasc0-2:1:w", "tempora": "", - "title": "Wednesday in the Octave of Easter", + "title": "Tuesday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-21": { + "2026-04-08": { + "id": "tempora:Pasc0-3:1:w", "tempora": "", - "title": "Monday in the Octave of Easter", + "title": "Wednesday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-24": { + "2026-04-09": { + "id": "tempora:Pasc0-4:1:w", "tempora": "", "title": "Thursday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-28": { - "tempora": "Monday after I Sunday after Easter", - "title": "St. Paul of the Cross", - "rank": 3, - "colour": "w" + "2026-04-10": { + "id": "tempora:Pasc0-5:1:w", + "tempora": "", + "title": "Friday in the Octave of Easter", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-04-26": { + "2026-04-11": { + "id": "tempora:Pasc0-6:1:w", "tempora": "", "title": "Saturday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-04": { + "2026-04-12": { + "id": "tempora:Pasc1-0:1:w", "tempora": "", - "title": "Feria VI after the IV Sunday of Lent", + "title": "Low Sunday", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-04-13": { + "id": "sancti:04-13:3:r", + "tempora": "Monday after I Sunday after Easter", + "title": "St. Hermenegild", "rank": 3, - "colour": "v" + "colours": [ + "r" + ] }, - "2025-05-04": { - "tempora": "", - "title": "II Sunday after Easter", - "rank": 2, - "colour": "w" + "2026-04-14": { + "id": "sancti:04-14:3:r", + "tempora": "Tuesday after I Sunday after Easter", + "title": "St. Justin", + "rank": 3, + "colours": [ + "r" + ] + }, + "2026-04-15": { + "id": "tempora:Pasc1-0:1:w", + "tempora": "Wednesday after I Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-05-01": { + "2026-04-16": { + "id": "tempora:Pasc1-0:1:w", "tempora": "Thursday after I Sunday after Easter", - "title": "St. Joseph the Workman", - "rank": 1, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-05-02": { + "2026-04-17": { + "id": "tempora:Pasc1-0:1:w", "tempora": "Friday after I Sunday after Easter", - "title": "St. Athanasius", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-04-15": { - "tempora": "", - "title": "Feria III of Holy Week", - "rank": 1, - "colour": "v" + "2026-04-18": { + "id": "commune:C10Pasc:4:w", + "tempora": "Saturday after I Sunday after Easter", + "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-04-29": { - "tempora": "Tuesday after I Sunday after Easter", - "title": "St. Peter of Verona", - "rank": 3, - "colour": "r" + "2026-04-19": { + "id": "tempora:Pasc2-0:2:w", + "tempora": "", + "title": "II Sunday after Easter", + "rank": 2, + "colours": [ + "w" + ] }, - "2025-05-08": { - "tempora": "Thursday after II Sunday after Easter", + "2026-04-20": { + "id": "tempora:Pasc2-0:2:w", + "tempora": "Monday after II Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-06": { + "2026-04-21": { + "id": "sancti:04-21:3:w", "tempora": "Tuesday after II Sunday after Easter", + "title": "St. Anselm", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-04-22": { + "id": "sancti:04-22:3:r", + "tempora": "Wednesday after II Sunday after Easter", + "title": "Sts. Soter & Caius", + "rank": 3, + "colours": [ + "r" + ] + }, + "2026-04-23": { + "id": "tempora:Pasc2-0:2:w", + "tempora": "Thursday after II Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-04-30": { - "tempora": "Wednesday after I Sunday after Easter", - "title": "St. Catherine of Siena", + "2026-04-24": { + "id": "sancti:04-24:3:r", + "tempora": "Friday after II Sunday after Easter", + "title": "St. Fidelis of Sigmaringen", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-04-05": { - "tempora": "", - "title": "Saturday after the IV Sunday of Lent", - "rank": 3, - "colour": "v" + "2026-04-25": { + "id": "sancti:04-25:2:r", + "tempora": "Saturday after II Sunday after Easter", + "title": "St. Mark", + "rank": 2, + "colours": [ + "r" + ] }, - "2025-04-16": { + "2026-04-26": { + "id": "tempora:Pasc3-0r:2:w", "tempora": "", - "title": "Feria IV of Holy Week", - "rank": 1, - "colour": "v" + "title": "III Sunday after Easter", + "rank": 2, + "colours": [ + "w" + ] }, - "2025-05-05": { - "tempora": "Monday after II Sunday after Easter", - "title": "St. Pius V", + "2026-04-27": { + "id": "sancti:04-27:3:w", + "tempora": "Monday after III Sunday after Easter", + "title": "St. Peter Canisius", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-12": { - "tempora": "Monday after III Sunday after Easter", - "title": "Sts. Nereus, Achilleus, Domitilla, & Pancras", + "2026-04-28": { + "id": "sancti:04-28:3:w", + "tempora": "Tuesday after III Sunday after Easter", + "title": "St. Paul of the Cross", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-05-09": { - "tempora": "Friday after II Sunday after Easter", - "title": "St. Gregory of Nazianzen", + "2026-04-29": { + "id": "sancti:04-29:3:r", + "tempora": "Wednesday after III Sunday after Easter", + "title": "St. Peter of Verona", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-05-07": { - "tempora": "Wednesday after II Sunday after Easter", - "title": "St. Stanislaus", + "2026-04-30": { + "id": "sancti:04-30:3:w", + "tempora": "Thursday after III Sunday after Easter", + "title": "St. Catherine of Siena", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-05-13": { - "tempora": "Tuesday after III Sunday after Easter", - "title": "St. Robert Bellarmine", + "2026-05-01": { + "id": "sancti:05-01r:1:w", + "tempora": "Friday after III Sunday after Easter", + "title": "St. Joseph the Workman", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-05-02": { + "id": "sancti:05-02:3:w", + "tempora": "Saturday after III Sunday after Easter", + "title": "St. Athanasius", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-18": { + "2026-05-03": { + "id": "tempora:Pasc4-0:2:w", "tempora": "", "title": "IV Sunday after Easter", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-11": { - "tempora": "", - "title": "III Sunday after Easter", - "rank": 2, - "colour": "w" + "2026-05-04": { + "id": "sancti:05-04:3:w", + "tempora": "Monday after IV Sunday after Easter", + "title": "St. Monica", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-05-22": { - "tempora": "Thursday after IV Sunday after Easter", - "title": "Feria", - "rank": 4, - "colour": "w" + "2026-05-05": { + "id": "sancti:05-05:3:w", + "tempora": "Tuesday after IV Sunday after Easter", + "title": "St. Pius V", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-05-21": { + "2026-05-06": { + "id": "tempora:Pasc4-0:2:w", "tempora": "Wednesday after IV Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-03": { - "tempora": "Saturday after I Sunday after Easter", - "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2026-05-07": { + "id": "sancti:05-07:3:r", + "tempora": "Thursday after IV Sunday after Easter", + "title": "St. Stanislaus", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-05-23": { + "2026-05-08": { + "id": "tempora:Pasc4-0:2:w", "tempora": "Friday after IV Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-14": { - "tempora": "Wednesday after III Sunday after Easter", - "title": "Feria", - "rank": 4, - "colour": "w" + "2026-05-09": { + "id": "sancti:05-09:3:w", + "tempora": "Saturday after IV Sunday after Easter", + "title": "St. Gregory of Nazianzen", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-05-29": { + "2026-05-10": { + "id": "tempora:Pasc5-0:2:w", "tempora": "", - "title": "Ascension of the Lord", - "rank": 1, - "colour": "w" + "title": "V Sunday after Easter", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-05-11": { + "id": "sancti:05-11r:2:r", + "tempora": "The Minor Litanies – Rogations", + "title": "Sts. Philip & James", + "rank": 2, + "colours": [ + "r" + ] + }, + "2026-05-12": { + "id": "sancti:05-12:3:r", + "tempora": "The Minor Litanies – Rogations", + "title": "Sts. Nereus, Achilleus, Domitilla, & Pancras", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-05-25": { + "2026-05-13": { + "id": "tempora:Pasc5-3:2:w", "tempora": "", - "title": "V Sunday after Easter", + "title": "Vigil of the Ascension", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-15": { - "tempora": "Thursday after III Sunday after Easter", + "2026-05-14": { + "id": "tempora:Pasc5-4:1:w", + "tempora": "", + "title": "Ascension of the Lord", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-05-15": { + "id": "sancti:05-15:3:w", + "tempora": "Feria VI after the Ascension", "title": "St. John Baptist de la Salle", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-17": { - "tempora": "Saturday after III Sunday after Easter", - "title": "St. Paschal Baylon", - "rank": 3, - "colour": "w" + "2026-05-16": { + "id": "commune:C10Pasc:4:w", + "tempora": "Saturday after the Ascension", + "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-05-20": { - "tempora": "Tuesday after IV Sunday after Easter", - "title": "St. Bernardine of Siena", - "rank": 3, - "colour": "w" + "2026-05-17": { + "id": "tempora:Pasc6-0:2:w", + "tempora": "", + "title": "Sunday after the Ascension", + "rank": 2, + "colours": [ + "w" + ] }, - "2025-05-10": { - "tempora": "Saturday after II Sunday after Easter", - "title": "St. Antoninus", + "2026-05-18": { + "id": "sancti:05-18:3:r", + "tempora": "Feria II after the Ascension", + "title": "St. Venantius", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-05-19": { - "tempora": "Monday after IV Sunday after Easter", + "2026-05-19": { + "id": "sancti:05-19:3:w", + "tempora": "Feria III after the Ascension", "title": "St. Peter Celestine", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-05-26": { - "tempora": "The Minor Litanies – Rogations", - "title": "St. Philip Neri", + "2026-05-20": { + "id": "sancti:05-20:3:w", + "tempora": "Feria IV after the Ascension", + "title": "St. Bernardine of Siena", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-06-01": { - "tempora": "", - "title": "Sunday after the Ascension", - "rank": 2, - "colour": "w" - }, - "2025-05-30": { - "tempora": "Feria VI after the Ascension", + "2026-05-21": { + "id": "tempora:Pasc6-0:2:w", + "tempora": "Feria V after the Ascension", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-06-08": { - "tempora": "", - "title": "Pentecost Sunday", - "rank": 1, - "colour": "r" - }, - "2025-05-28": { - "tempora": "", - "title": "Vigil of the Ascension", - "rank": 2, - "colour": "w" - }, - "2025-06-03": { - "tempora": "Feria III after the Ascension", + "2026-05-22": { + "id": "tempora:Pasc6-0:2:w", + "tempora": "Feria VI after the Ascension", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-06-07": { + "2026-05-23": { + "id": "tempora:Pasc6-6:1:r", "tempora": "", "title": "Saturday after the Ascension", "rank": 1, - "colour": "r" - }, - "2025-05-24": { - "tempora": "Saturday after IV Sunday after Easter", - "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" - }, - "2025-05-31": { - "tempora": "Saturday after the Ascension", - "title": "Queenship of the Blessed Virgin Mary", - "rank": 2, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-06-05": { - "tempora": "Feria V after the Ascension", - "title": "St. Boniface", - "rank": 3, - "colour": "r" - }, - "2025-06-09": { + "2026-05-24": { + "id": "tempora:Pasc7-0:1:r", "tempora": "", - "title": "Monday after Pentecost", + "title": "Pentecost Sunday", "rank": 1, - "colour": "r" - }, - "2025-05-16": { - "tempora": "Friday after III Sunday after Easter", - "title": "Feria", - "rank": 4, - "colour": "w" - }, - "2025-06-04": { - "tempora": "Feria IV after the Ascension", - "title": "St. Francis Caracciolo", - "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-06-15": { + "2026-05-25": { + "id": "tempora:Pasc7-1:1:r", "tempora": "", - "title": "Trinity Sunday", + "title": "Monday after Pentecost", "rank": 1, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-06-10": { + "2026-05-26": { + "id": "tempora:Pasc7-2:1:r", "tempora": "", "title": "Tuesday after Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-05-27": { - "tempora": "The Minor Litanies – Rogations", - "title": "St. Bede the Venerable", - "rank": 3, - "colour": "w" + "2026-05-27": { + "id": "tempora:Pasc7-3:1:r", + "tempora": "", + "title": "Ember Wednesday of Pentecost", + "rank": 1, + "colours": [ + "r" + ] }, - "2025-06-02": { - "tempora": "Feria II after the Ascension", - "title": "Feria", - "rank": 4, - "colour": "w" + "2026-05-28": { + "id": "tempora:Pasc7-4:1:r", + "tempora": "", + "title": "Thursday after Pentecost", + "rank": 1, + "colours": [ + "r" + ] }, - "2025-06-13": { + "2026-05-29": { + "id": "tempora:Pasc7-5:1:r", "tempora": "", "title": "Ember Friday of Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-06-12": { + "2026-05-30": { + "id": "tempora:Pasc7-6:1:r", "tempora": "", - "title": "Thursday after Pentecost", + "title": "Ember Saturday of Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-06-22": { + "2026-05-31": { + "id": "tempora:Pent01-0r:1:w", "tempora": "", - "title": "II Sunday after Pentecost", - "rank": 2, - "colour": "g" + "title": "Trinity Sunday", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-06-16": { + "2026-06-01": { + "id": "sancti:06-01:3:w", "tempora": "Feria II after I Sunday after Pentecost", + "title": "St. Angela Merici", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-06-02": { + "id": "tempora:Pent01-0a:2:g", + "tempora": "Feria III after I Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-06-11": { - "tempora": "", - "title": "Ember Wednesday of Pentecost", - "rank": 1, - "colour": "r" - }, - "2025-06-23": { - "tempora": "Feria II after II Sunday after Pentecost", - "title": "Vigil of the Nativity of St. John the Baptist", - "rank": 2, - "colour": "v" + "2026-06-03": { + "id": "tempora:Pent01-0a:2:g", + "tempora": "Feria IV after I Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-06-19": { + "2026-06-04": { + "id": "tempora:Pent01-4:1:w", "tempora": "", "title": "Corpus Christi", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-06-24": { - "tempora": "Feria III after II Sunday after Pentecost", - "title": "Nativity of St. John the Baptist", - "rank": 1, - "colour": "w" - }, - "2025-06-21": { - "tempora": "Saturday after I Sunday after Pentecost", - "title": "St. Aloysius Gongzaga", + "2026-06-05": { + "id": "sancti:06-05:3:r", + "tempora": "Feria V after I Sunday after Pentecost", + "title": "St. Boniface", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-06-26": { - "tempora": "Feria V after II Sunday after Pentecost", - "title": "Sts. John & Paul", + "2026-06-06": { + "id": "sancti:06-06:3:w", + "tempora": "Saturday after I Sunday after Pentecost", + "title": "St. Norbert", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-06-25": { - "tempora": "Feria IV after II Sunday after Pentecost", - "title": "St. William", - "rank": 3, - "colour": "w" + "2026-06-07": { + "id": "tempora:Pent02-0r:2:g", + "tempora": "", + "title": "II Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-06-20": { - "tempora": "Feria V after I Sunday after Pentecost", + "2026-06-08": { + "id": "tempora:Pent02-0r:2:g", + "tempora": "Feria II after II Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-06-27": { - "tempora": "", - "title": "Sacred Heart of Jesus", - "rank": 1, - "colour": "w" + "2026-06-09": { + "id": "tempora:Pent02-0r:2:g", + "tempora": "Feria III after II Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-06-28": { - "tempora": "Saturday after II Sunday after Pentecost", - "title": "Vigil of Sts. Peter & Paul", - "rank": 2, - "colour": "v" + "2026-06-10": { + "id": "sancti:06-10:3:w", + "tempora": "Feria IV after II Sunday after Pentecost", + "title": "St. Margaret of Scotland", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-06-06": { - "tempora": "Feria VI after the Ascension", - "title": "St. Norbert", + "2026-06-11": { + "id": "sancti:06-11:3:r", + "tempora": "Feria V after II Sunday after Pentecost", + "title": "St. Barnabas", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-07-01": { - "tempora": "Feria III after III Sunday after Pentecost", - "title": "The Precious Blood of Our Lord Jesus Christ", + "2026-06-12": { + "id": "tempora:Pent02-5:1:w", + "tempora": "", + "title": "Sacred Heart of Jesus", "rank": 1, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-06-18": { - "tempora": "Feria IV after I Sunday after Pentecost", - "title": "St. Ephrem of Syria", + "2026-06-13": { + "id": "sancti:06-13:3:w", + "tempora": "Saturday after II Sunday after Pentecost", + "title": "St. Anthony of Padua", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-07-06": { + "2026-06-14": { + "id": "tempora:Pent03-0r:2:g", "tempora": "", - "title": "IV Sunday after Pentecost", + "title": "III Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-06-30": { + "2026-06-15": { + "id": "tempora:Pent03-0r:2:g", "tempora": "Feria II after III Sunday after Pentecost", - "title": "In Commemoratione Sancti Pauli Apostoli", - "rank": 3, - "colour": "r" - }, - "2025-06-29": { - "tempora": "III Sunday after Pentecost", - "title": "Sts. Peter & Paul", - "rank": 1, - "colour": "r" - }, - "2025-07-03": { - "tempora": "Feria V after III Sunday after Pentecost", - "title": "St. Irenaeus", - "rank": 3, - "colour": "r" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-07-04": { - "tempora": "Feria VI after III Sunday after Pentecost", + "2026-06-16": { + "id": "tempora:Pent03-0r:2:g", + "tempora": "Feria III after III Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-06-17": { - "tempora": "Feria III after I Sunday after Pentecost", + "2026-06-17": { + "id": "sancti:06-17r:3:w", + "tempora": "Feria IV after III Sunday after Pentecost", "title": "St. Gregory Barbarigo", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-07-05": { - "tempora": "Saturday after III Sunday after Pentecost", - "title": "St. Anthony Mary Zaccariah", + "2026-06-18": { + "id": "sancti:06-18:3:r", + "tempora": "Feria V after III Sunday after Pentecost", + "title": "St. Ephrem of Syria", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-07-09": { - "tempora": "Feria IV after IV Sunday after Pentecost", - "title": "Feria", + "2026-06-19": { + "id": "sancti:06-19:3:r", + "tempora": "Feria VI after III Sunday after Pentecost", + "title": "St. Julia of Falconieri", + "rank": 3, + "colours": [ + "r" + ] + }, + "2026-06-20": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after III Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-07-08": { - "tempora": "Feria III after IV Sunday after Pentecost", - "title": "St. Elizabeth of Portugal", - "rank": 3, - "colour": "w" + "2026-06-21": { + "id": "tempora:Pent04-0:2:g", + "tempora": "", + "title": "IV Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-07-07": { + "2026-06-22": { + "id": "sancti:06-22:3:w", "tempora": "Feria II after IV Sunday after Pentecost", - "title": "Sts. Cyril & Methodius", + "title": "St. Paulinus of Nola", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-07-10": { + "2026-06-23": { + "id": "sancti:06-23:2:v", + "tempora": "Feria III after IV Sunday after Pentecost", + "title": "Vigil of the Nativity of St. John the Baptist", + "rank": 2, + "colours": [ + "v" + ] + }, + "2026-06-24": { + "id": "sancti:06-24:1:w", + "tempora": "Feria IV after IV Sunday after Pentecost", + "title": "Nativity of St. John the Baptist", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-06-25": { + "id": "sancti:06-25:3:w", "tempora": "Feria V after IV Sunday after Pentecost", - "title": "Seven Holy Brothers and Sts. Rufina & Secunda", + "title": "St. William", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-07-13": { + "2026-06-26": { + "id": "sancti:06-26:3:r", + "tempora": "Feria VI after IV Sunday after Pentecost", + "title": "Sts. John & Paul", + "rank": 3, + "colours": [ + "r" + ] + }, + "2026-06-27": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after IV Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2026-06-28": { + "id": "tempora:Pent05-0:2:g", "tempora": "", "title": "V Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-19": { - "tempora": "Saturday after V Sunday after Pentecost", - "title": "St. Vincent de Paul", + "2026-06-29": { + "id": "sancti:06-29:1:r", + "tempora": "Feria II after V Sunday after Pentecost", + "title": "Sts. Peter & Paul", + "rank": 1, + "colours": [ + "r" + ] + }, + "2026-06-30": { + "id": "sancti:06-30:3:r", + "tempora": "Feria III after V Sunday after Pentecost", + "title": "In Commemoratione Sancti Pauli Apostoli", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-07-02": { - "tempora": "Feria IV after III Sunday after Pentecost", + "2026-07-01": { + "id": "sancti:07-01:1:r", + "tempora": "Feria IV after V Sunday after Pentecost", + "title": "The Precious Blood of Our Lord Jesus Christ", + "rank": 1, + "colours": [ + "r" + ] + }, + "2026-07-02": { + "id": "sancti:07-02:2:w", + "tempora": "Feria V after V Sunday after Pentecost", "title": "Visitation of the Blessed Virgin Mary", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-06-14": { - "tempora": "", - "title": "Ember Saturday of Pentecost", - "rank": 1, - "colour": "r" + "2026-07-03": { + "id": "sancti:07-03r:3:r", + "tempora": "Feria VI after V Sunday after Pentecost", + "title": "St. Irenaeus", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-07-20": { + "2026-07-04": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after V Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2026-07-05": { + "id": "tempora:Pent06-0:2:g", "tempora": "", "title": "VI Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-11": { - "tempora": "Feria VI after IV Sunday after Pentecost", + "2026-07-06": { + "id": "tempora:Pent06-0:2:g", + "tempora": "Feria II after VI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-22": { + "2026-07-07": { + "id": "sancti:07-07:3:w", "tempora": "Feria III after VI Sunday after Pentecost", - "title": "St. Mary Magdalene", + "title": "Sts. Cyril & Methodius", "rank": 3, - "colour": "w" - }, - "2025-07-16": { - "tempora": "Feria IV after V Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-07-12": { - "tempora": "Saturday after IV Sunday after Pentecost", - "title": "St. John Gualbert", + "2026-07-08": { + "id": "sancti:07-08:3:w", + "tempora": "Feria IV after VI Sunday after Pentecost", + "title": "St. Elizabeth of Portugal", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-07-14": { - "tempora": "Feria II after V Sunday after Pentecost", - "title": "St. Bonaventure", - "rank": 3, - "colour": "w" + "2026-07-09": { + "id": "tempora:Pent06-0:2:g", + "tempora": "Feria V after VI Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-07-18": { - "tempora": "Feria VI after V Sunday after Pentecost", - "title": "Camillus de Lellis", + "2026-07-10": { + "id": "sancti:07-10:3:r", + "tempora": "Feria VI after VI Sunday after Pentecost", + "title": "Seven Holy Brothers and Sts. Rufina & Secunda", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-07-26": { + "2026-07-11": { + "id": "commune:C10t:4:w", "tempora": "Saturday after VI Sunday after Pentecost", - "title": "St. Anne, Mother of the Blessed Virgin", - "rank": 2, - "colour": "w" - }, - "2025-07-15": { - "tempora": "Feria III after V Sunday after Pentecost", - "title": "St. Henry the Emperor", - "rank": 3, - "colour": "w" + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2025-07-27": { + "2026-07-12": { + "id": "tempora:Pent07-0:2:g", "tempora": "", "title": "VII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-25": { - "tempora": "Feria VI after VI Sunday after Pentecost", - "title": "St. James the Greater", - "rank": 2, - "colour": "r" - }, - "2025-07-24": { - "tempora": "Feria V after VI Sunday after Pentecost", + "2026-07-13": { + "id": "tempora:Pent07-0:2:g", + "tempora": "Feria II after VII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-31": { - "tempora": "Feria V after VII Sunday after Pentecost", - "title": "St. Ignatius Loyola", + "2026-07-14": { + "id": "sancti:07-14:3:w", + "tempora": "Feria III after VII Sunday after Pentecost", + "title": "St. Bonaventure", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-03": { - "tempora": "", - "title": "VIII Sunday after Pentecost", - "rank": 2, - "colour": "g" - }, - "2025-07-17": { - "tempora": "Feria V after V Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2025-07-21": { - "tempora": "Feria II after VI Sunday after Pentecost", - "title": "St. Laurence of Brindisi", + "2026-07-15": { + "id": "sancti:07-15:3:w", + "tempora": "Feria IV after VII Sunday after Pentecost", + "title": "St. Henry the Emperor", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-01": { - "tempora": "Feria VI after VII Sunday after Pentecost", + "2026-07-16": { + "id": "tempora:Pent07-0:2:g", + "tempora": "Feria V after VII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" - }, - "2025-07-29": { - "tempora": "Feria III after VII Sunday after Pentecost", - "title": "St. Martha", - "rank": 3, - "colour": "r" + "colours": [ + "g" + ] }, - "2025-07-28": { - "tempora": "Feria II after VII Sunday after Pentecost", - "title": "Sts. Nazarius & Celsus, St. Victor I & St. Innocent I", - "rank": 3, - "colour": "r" - }, - "2025-07-30": { - "tempora": "Feria IV after VII Sunday after Pentecost", + "2026-07-17": { + "id": "tempora:Pent07-0:2:g", + "tempora": "Feria VI after VII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-02": { + "2026-07-18": { + "id": "sancti:07-18:3:r", "tempora": "Saturday after VII Sunday after Pentecost", - "title": "St. Alphonsus Liguori", + "title": "Camillus de Lellis", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] + }, + "2026-07-19": { + "id": "tempora:Pent08-0:2:g", + "tempora": "", + "title": "VIII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-08-04": { + "2026-07-20": { + "id": "sancti:07-20:3:r", "tempora": "Feria II after VIII Sunday after Pentecost", - "title": "St. Dominic", + "title": "St. Jerome Emiliani", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-08-15": { - "tempora": "Feria VI after IX Sunday after Pentecost", - "title": "Assumption of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" + "2026-07-21": { + "id": "sancti:07-21r:3:w", + "tempora": "Feria III after VIII Sunday after Pentecost", + "title": "St. Laurence of Brindisi", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-08-06": { + "2026-07-22": { + "id": "sancti:07-22:3:w", "tempora": "Feria IV after VIII Sunday after Pentecost", - "title": "Transfiguration of Our Lord", - "rank": 2, - "colour": "w" + "title": "St. Mary Magdalene", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-08-12": { - "tempora": "Feria III after IX Sunday after Pentecost", - "title": "St. Clare", + "2026-07-23": { + "id": "sancti:07-23:3:w", + "tempora": "Feria V after VIII Sunday after Pentecost", + "title": "St. Apollinaris", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-11": { - "tempora": "Feria II after IX Sunday after Pentecost", + "2026-07-24": { + "id": "tempora:Pent08-0:2:g", + "tempora": "Feria VI after VIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-17": { - "tempora": "", - "title": "X Sunday after Pentecost", + "2026-07-25": { + "id": "sancti:07-25:2:r", + "tempora": "Saturday after VIII Sunday after Pentecost", + "title": "St. James the Greater", "rank": 2, - "colour": "g" + "colours": [ + "r" + ] }, - "2025-08-10": { + "2026-07-26": { + "id": "tempora:Pent09-0:2:g", "tempora": "", "title": "IX Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-13": { - "tempora": "Feria IV after IX Sunday after Pentecost", + "2026-07-27": { + "id": "tempora:Pent09-0:2:g", + "tempora": "Feria II after IX Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-05": { - "tempora": "Feria III after VIII Sunday after Pentecost", - "title": "Dedication of the Basilica of St. Mary Major", + "2026-07-28": { + "id": "sancti:07-28:3:r", + "tempora": "Feria III after IX Sunday after Pentecost", + "title": "Sts. Nazarius & Celsus, St. Victor I & St. Innocent I", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-08-07": { - "tempora": "Feria V after VIII Sunday after Pentecost", - "title": "St. Cajetan", + "2026-07-29": { + "id": "sancti:07-29:3:r", + "tempora": "Feria IV after IX Sunday after Pentecost", + "title": "St. Martha", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-08-16": { - "tempora": "Saturday after IX Sunday after Pentecost", - "title": "St. Joachim, Father of the Blessed Virgin", - "rank": 2, - "colour": "w" + "2026-07-30": { + "id": "tempora:Pent09-0:2:g", + "tempora": "Feria V after IX Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-08-21": { - "tempora": "Feria V after X Sunday after Pentecost", - "title": "St. Jane Frances de Chantal", + "2026-07-31": { + "id": "sancti:07-31:3:w", + "tempora": "Feria VI after IX Sunday after Pentecost", + "title": "St. Ignatius Loyola", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] + }, + "2026-08-01": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after IX Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2026-08-02": { + "id": "tempora:Pent10-0:2:g", + "tempora": "", + "title": "X Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-08-18": { + "2026-08-03": { + "id": "tempora:Pent10-0:2:g", "tempora": "Feria II after X Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-07-23": { - "tempora": "Feria IV after VI Sunday after Pentecost", - "title": "St. Apollinaris", + "2026-08-04": { + "id": "sancti:08-04:3:w", + "tempora": "Feria III after X Sunday after Pentecost", + "title": "St. Dominic", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-08": { - "tempora": "Feria VI after VIII Sunday after Pentecost", - "title": "St. John Mary Vianney", + "2026-08-05": { + "id": "sancti:08-05:3:w", + "tempora": "Feria IV after X Sunday after Pentecost", + "title": "Dedication of the Basilica of St. Mary Major", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-23": { - "tempora": "Saturday after X Sunday after Pentecost", - "title": "St. Philip Benizi", + "2026-08-06": { + "id": "sancti:08-06:2:w", + "tempora": "Feria V after X Sunday after Pentecost", + "title": "Transfiguration of Our Lord", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-08-07": { + "id": "sancti:08-07:3:w", + "tempora": "Feria VI after X Sunday after Pentecost", + "title": "St. Cajetan", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-20": { - "tempora": "Feria IV after X Sunday after Pentecost", - "title": "St. Bernard of Clairvaux", + "2026-08-08": { + "id": "sancti:08-08:3:w", + "tempora": "Saturday after X Sunday after Pentecost", + "title": "St. John Mary Vianney", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-22": { - "tempora": "Feria VI after X Sunday after Pentecost", - "title": "Immaculate Heart of Mary", - "rank": 2, - "colour": "w" + "2026-08-09": { + "id": "sancti:08-09t:3:r", + "tempora": "XI Sunday after Pentecost", + "title": "Vigil of St. Lawrence", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-08-14": { - "tempora": "Feria V after IX Sunday after Pentecost", - "title": "Vigil of the Assumption", + "2026-08-10": { + "id": "sancti:08-10:2:r", + "tempora": "Feria II after XI Sunday after Pentecost", + "title": "St. Lawrence", "rank": 2, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-08-25": { - "tempora": "Feria II after XI Sunday after Pentecost", - "title": "St. Louis IX", - "rank": 3, - "colour": "w" + "2026-08-11": { + "id": "tempora:Pent11-0:2:g", + "tempora": "Feria III after XI Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-08-27": { + "2026-08-12": { + "id": "sancti:08-12:3:w", "tempora": "Feria IV after XI Sunday after Pentecost", - "title": "St. Joseph Calasance", + "title": "St. Clare", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-31": { - "tempora": "", - "title": "XII Sunday after Pentecost", + "2026-08-13": { + "id": "tempora:Pent11-0:2:g", + "tempora": "Feria V after XI Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-08-14": { + "id": "sancti:08-14:2:w", + "tempora": "Feria VI after XI Sunday after Pentecost", + "title": "Vigil of the Assumption", "rank": 2, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-08-24": { + "2026-08-15": { + "id": "sancti:08-15:1:w", + "tempora": "Saturday after XI Sunday after Pentecost", + "title": "Assumption of the Blessed Virgin Mary", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-08-16": { + "id": "tempora:Pent12-0:2:g", "tempora": "", - "title": "XI Sunday after Pentecost", + "title": "XII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-09": { - "tempora": "Saturday after VIII Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2026-08-17": { + "id": "sancti:08-17:3:w", + "tempora": "Feria II after XII Sunday after Pentecost", + "title": "St. Hyacinth", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-08-26": { - "tempora": "Feria III after XI Sunday after Pentecost", + "2026-08-18": { + "id": "tempora:Pent12-0:2:g", + "tempora": "Feria III after XII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-08-19": { - "tempora": "Feria III after X Sunday after Pentecost", + "2026-08-19": { + "id": "sancti:08-19:3:w", + "tempora": "Feria IV after XII Sunday after Pentecost", "title": "St. John Eudes", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-04": { + "2026-08-20": { + "id": "sancti:08-20:3:w", "tempora": "Feria V after XII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Bernard of Clairvaux", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-09-03": { - "tempora": "Feria IV after XII Sunday after Pentecost", - "title": "St. Pius X", + "2026-08-21": { + "id": "sancti:08-21:3:w", + "tempora": "Feria VI after XII Sunday after Pentecost", + "title": "St. Jane Frances de Chantal", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-07": { + "2026-08-22": { + "id": "sancti:08-22:2:w", + "tempora": "Saturday after XII Sunday after Pentecost", + "title": "Immaculate Heart of Mary", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-08-23": { + "id": "tempora:Pent13-0:2:g", "tempora": "", "title": "XIII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-02": { - "tempora": "Feria III after XII Sunday after Pentecost", - "title": "St. Stephen of Hungary", + "2026-08-24": { + "id": "sancti:08-24:2:r", + "tempora": "Feria II after XIII Sunday after Pentecost", + "title": "St. Bartholomew", + "rank": 2, + "colours": [ + "r" + ] + }, + "2026-08-25": { + "id": "sancti:08-25:3:w", + "tempora": "Feria III after XIII Sunday after Pentecost", + "title": "St. Louis IX", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-08-30": { - "tempora": "Saturday after XI Sunday after Pentecost", - "title": "St. Rose of Lima", + "2026-08-26": { + "id": "tempora:Pent13-0:2:g", + "tempora": "Feria IV after XIII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-08-27": { + "id": "sancti:08-27:3:w", + "tempora": "Feria V after XIII Sunday after Pentecost", + "title": "St. Joseph Calasance", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-08-28": { - "tempora": "Feria V after XI Sunday after Pentecost", + "2026-08-28": { + "id": "sancti:08-28:3:r", + "tempora": "Feria VI after XIII Sunday after Pentecost", "title": "St. Augustine", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-09-10": { - "tempora": "Feria IV after XIII Sunday after Pentecost", - "title": "St. Nicholas of Tolentino", + "2026-08-29": { + "id": "sancti:08-29:3:r", + "tempora": "Saturday after XIII Sunday after Pentecost", + "title": "Beheading of St. John the Baptist", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-08-29": { - "tempora": "Feria VI after XI Sunday after Pentecost", - "title": "Beheading of St. John the Baptist", + "2026-08-30": { + "id": "tempora:Pent14-0:2:g", + "tempora": "", + "title": "XIV Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2026-08-31": { + "id": "sancti:08-31:3:w", + "tempora": "Feria II after XIV Sunday after Pentecost", + "title": "St. Raymond Nonnatus", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-09-09": { - "tempora": "Feria III after XIII Sunday after Pentecost", + "2026-09-01": { + "id": "tempora:Pent14-0:2:g", + "tempora": "Feria III after XIV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-14": { - "tempora": "XIV Sunday after Pentecost", - "title": "Exaltation of the Holy Cross", + "2026-09-02": { + "id": "sancti:09-02:3:w", + "tempora": "Feria IV after XIV Sunday after Pentecost", + "title": "St. Stephen of Hungary", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-09-03": { + "id": "sancti:09-03:3:w", + "tempora": "Feria V after XIV Sunday after Pentecost", + "title": "St. Pius X", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-09-04": { + "id": "tempora:Pent14-0:2:g", + "tempora": "Feria VI after XIV Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-09-05": { + "id": "sancti:09-05:3:w", + "tempora": "Saturday after XIV Sunday after Pentecost", + "title": "St. Lawrence Justinian", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-09-06": { + "id": "tempora:Pent15-0:2:g", + "tempora": "", + "title": "XV Sunday after Pentecost", "rank": 2, - "colour": "r" + "colours": [ + "g" + ] }, - "2025-09-08": { - "tempora": "Feria II after XIII Sunday after Pentecost", + "2026-09-07": { + "id": "tempora:Pent15-0:2:g", + "tempora": "Feria II after XV Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-09-08": { + "id": "sancti:09-08:2:w", + "tempora": "Feria III after XV Sunday after Pentecost", "title": "Nativity of the Blessed Virgin Mary", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-11": { - "tempora": "Feria V after XIII Sunday after Pentecost", + "2026-09-09": { + "id": "tempora:Pent15-0:2:g", + "tempora": "Feria IV after XV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-01": { - "tempora": "Feria II after XII Sunday after Pentecost", + "2026-09-10": { + "id": "sancti:09-10:3:w", + "tempora": "Feria V after XV Sunday after Pentecost", + "title": "St. Nicholas of Tolentino", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-09-11": { + "id": "tempora:Pent15-0:2:g", + "tempora": "Feria VI after XV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-12": { - "tempora": "Feria VI after XIII Sunday after Pentecost", + "2026-09-12": { + "id": "sancti:09-12:3:w", + "tempora": "Saturday after XV Sunday after Pentecost", "title": "Most Holy Name of Mary", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-19": { - "tempora": "Feria VI after XIV Sunday after Pentecost", - "title": "St. Januarius & Companions", + "2026-09-13": { + "id": "tempora:Pent16-0:2:g", + "tempora": "", + "title": "XVI Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2026-09-14": { + "id": "sancti:09-14:2:r", + "tempora": "Feria II after XVI Sunday after Pentecost", + "title": "Exaltation of the Holy Cross", + "rank": 2, + "colours": [ + "r" + ] + }, + "2026-09-15": { + "id": "sancti:09-15:2:w", + "tempora": "Feria III after XVI Sunday after Pentecost", + "title": "Seven Sorrows of the Blessed Virgin Mary", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-09-16": { + "id": "sancti:09-16:3:r", + "tempora": "Feria IV after XVI Sunday after Pentecost", + "title": "Sts. Cornelius & Cyprian", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-09-18": { - "tempora": "Feria V after XIV Sunday after Pentecost", + "2026-09-17": { + "id": "tempora:Pent16-0:2:g", + "tempora": "Feria V after XVI Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-09-18": { + "id": "sancti:09-18:3:w", + "tempora": "Feria VI after XVI Sunday after Pentecost", "title": "St. Joseph of Cupertino", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-05": { - "tempora": "Feria VI after XII Sunday after Pentecost", - "title": "St. Lawrence Justinian", + "2026-09-19": { + "id": "sancti:09-19:3:r", + "tempora": "Saturday after XVI Sunday after Pentecost", + "title": "St. Januarius & Companions", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-09-06": { - "tempora": "Saturday after XII Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2026-09-20": { + "id": "tempora:Pent17-0:2:g", + "tempora": "", + "title": "XVII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2025-09-25": { - "tempora": "Feria V after XV Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2026-09-21": { + "id": "sancti:09-21:2:r", + "tempora": "Feria II after XVII Sunday after Pentecost", + "title": "St. Matthew", + "rank": 2, + "colours": [ + "r" + ] }, - "2025-09-17": { - "tempora": "Feria IV after XIV Sunday after Pentecost", + "2026-09-22": { + "id": "sancti:09-22:3:w", + "tempora": "Feria III after XVII Sunday after Pentecost", + "title": "St. Thomas of Villanova", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-09-23": { + "id": "tempora:093-3:2:v", + "tempora": "", + "title": "Ember Wednesday of September", + "rank": 2, + "colours": [ + "v" + ] + }, + "2026-09-24": { + "id": "tempora:Pent17-0:2:g", + "tempora": "Feria V after XVII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-15": { - "tempora": "Feria II after XIV Sunday after Pentecost", - "title": "Seven Sorrows of the Blessed Virgin Mary", + "2026-09-25": { + "id": "tempora:093-5:2:v", + "tempora": "", + "title": "Ember Friday of September", "rank": 2, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-09-26": { + "2026-09-26": { + "id": "tempora:093-6:2:v", "tempora": "", - "title": "Ember Friday of September", + "title": "Ember Saturday of September", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-09-21": { + "2026-09-27": { + "id": "tempora:Pent18-0:2:g", "tempora": "", - "title": "XV Sunday after Pentecost", + "title": "XVIII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-09-13": { - "tempora": "Saturday after XIII Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2026-09-28": { + "id": "sancti:09-28:3:r", + "tempora": "Feria II after XVIII Sunday after Pentecost", + "title": "St. Wenceslaus", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-09-29": { - "tempora": "Feria II after XVI Sunday after Pentecost", + "2026-09-29": { + "id": "sancti:09-29:1:w", + "tempora": "Feria III after XVIII Sunday after Pentecost", "title": "Dedication of St. Michael the Archangel", "rank": 1, - "colour": "w" - }, - "2025-09-28": { - "tempora": "", - "title": "XVI Sunday after Pentecost", - "rank": 2, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-09-30": { - "tempora": "Feria III after XVI Sunday after Pentecost", + "2026-09-30": { + "id": "sancti:09-30:3:w", + "tempora": "Feria IV after XVIII Sunday after Pentecost", "title": "St. Jerome", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-03": { - "tempora": "Feria VI after XVI Sunday after Pentecost", - "title": "St. Theresa of the Infant Jesus", - "rank": 3, - "colour": "w" - }, - "2025-10-05": { - "tempora": "", - "title": "XVII Sunday after Pentecost", - "rank": 2, - "colour": "g" + "2026-10-01": { + "id": "tempora:Pent18-0:2:g", + "tempora": "Feria V after XVIII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-10-02": { - "tempora": "Feria V after XVI Sunday after Pentecost", + "2026-10-02": { + "id": "sancti:10-02:3:w", + "tempora": "Feria VI after XVIII Sunday after Pentecost", "title": "Holy Guardian Angels", "rank": 3, - "colour": "w" - }, - "2025-10-04": { - "tempora": "Saturday after XVI Sunday after Pentecost", - "title": "St. Francis of Assisi", - "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-20": { - "tempora": "Saturday after XIV Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" - }, - "2025-10-09": { - "tempora": "Feria V after XVII Sunday after Pentecost", - "title": "St. John Leonardi", + "2026-10-03": { + "id": "sancti:10-03:3:w", + "tempora": "Saturday after XVIII Sunday after Pentecost", + "title": "St. Theresa of the Infant Jesus", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-24": { + "2026-10-04": { + "id": "tempora:Pent19-0:2:g", "tempora": "", - "title": "Ember Wednesday of September", + "title": "XIX Sunday after Pentecost", "rank": 2, - "colour": "v" + "colours": [ + "g" + ] }, - "2025-10-08": { - "tempora": "Feria IV after XVII Sunday after Pentecost", - "title": "St. Bridget of Sweden", - "rank": 3, - "colour": "w" - }, - "2025-09-23": { - "tempora": "Feria III after XV Sunday after Pentecost", - "title": "St. Linus", - "rank": 3, - "colour": "r" + "2026-10-05": { + "id": "tempora:Pent19-0:2:g", + "tempora": "Feria II after XIX Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-10-10": { - "tempora": "Feria VI after XVII Sunday after Pentecost", - "title": "St. Francis Borgia", + "2026-10-06": { + "id": "sancti:10-06:3:w", + "tempora": "Feria III after XIX Sunday after Pentecost", + "title": "St. Bruno", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-07": { - "tempora": "Feria III after XVII Sunday after Pentecost", + "2026-10-07": { + "id": "sancti:10-07:2:w", + "tempora": "Feria IV after XIX Sunday after Pentecost", "title": "Our Lady of the Rosary", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-14": { - "tempora": "Feria III after XVIII Sunday after Pentecost", - "title": "St. Callistus I", + "2026-10-08": { + "id": "sancti:10-08:3:w", + "tempora": "Feria V after XIX Sunday after Pentecost", + "title": "St. Bridget of Sweden", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-10-06": { - "tempora": "Feria II after XVII Sunday after Pentecost", - "title": "St. Bruno", + "2026-10-09": { + "id": "sancti:10-09:3:w", + "tempora": "Feria VI after XIX Sunday after Pentecost", + "title": "St. John Leonardi", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-27": { - "tempora": "", - "title": "Ember Saturday of September", - "rank": 2, - "colour": "v" + "2026-10-10": { + "id": "sancti:10-10:3:w", + "tempora": "Saturday after XIX Sunday after Pentecost", + "title": "St. Francis Borgia", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-10-12": { + "2026-10-11": { + "id": "tempora:Pent20-0:2:g", "tempora": "", - "title": "XVIII Sunday after Pentecost", + "title": "XX Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-11": { - "tempora": "Saturday after XVII Sunday after Pentecost", - "title": "Maternity of the Blessed Virgin Mary", - "rank": 2, - "colour": "w" + "2026-10-12": { + "id": "tempora:Pent20-0:2:g", + "tempora": "Feria II after XX Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2025-09-22": { - "tempora": "Feria II after XV Sunday after Pentecost", - "title": "St. Thomas of Villanova", + "2026-10-13": { + "id": "sancti:10-13:3:w", + "tempora": "Feria III after XX Sunday after Pentecost", + "title": "St. Edward", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-09-16": { - "tempora": "Feria III after XIV Sunday after Pentecost", - "title": "Sts. Cornelius & Cyprian", + "2026-10-14": { + "id": "sancti:10-14:3:r", + "tempora": "Feria IV after XX Sunday after Pentecost", + "title": "St. Callistus I", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-10-15": { - "tempora": "Feria IV after XVIII Sunday after Pentecost", + "2026-10-15": { + "id": "sancti:10-15:3:w", + "tempora": "Feria V after XX Sunday after Pentecost", "title": "St. Teresa of Avila", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-16": { - "tempora": "Feria V after XVIII Sunday after Pentecost", + "2026-10-16": { + "id": "sancti:10-16:3:w", + "tempora": "Feria VI after XX Sunday after Pentecost", "title": "St. Hedwig", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-26": { - "tempora": "XX Sunday after Pentecost", - "title": "Christ the King", - "rank": 1, - "colour": "w" - }, - "2025-10-18": { - "tempora": "Saturday after XVIII Sunday after Pentecost", - "title": "St. Luke the Evangelist", - "rank": 2, - "colour": "r" - }, - "2025-10-17": { - "tempora": "Feria VI after XVIII Sunday after Pentecost", + "2026-10-17": { + "id": "sancti:10-17:3:w", + "tempora": "Saturday after XX Sunday after Pentecost", "title": "St. Margaret Mary Alacoque", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-19": { + "2026-10-18": { + "id": "tempora:Pent21-0:2:g", "tempora": "", - "title": "XIX Sunday after Pentecost", + "title": "XXI Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-20": { - "tempora": "Feria II after XIX Sunday after Pentecost", + "2026-10-19": { + "id": "sancti:10-19:3:w", + "tempora": "Feria II after XXI Sunday after Pentecost", + "title": "St. Peter of Alcantara", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-10-20": { + "id": "sancti:10-20:3:w", + "tempora": "Feria III after XXI Sunday after Pentecost", "title": "St. John Cantius", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-22": { - "tempora": "Feria IV after XIX Sunday after Pentecost", + "2026-10-21": { + "id": "tempora:Pent21-0:2:g", + "tempora": "Feria IV after XXI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-23": { - "tempora": "Feria V after XIX Sunday after Pentecost", + "2026-10-22": { + "id": "tempora:Pent21-0:2:g", + "tempora": "Feria V after XXI Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-10-23": { + "id": "sancti:10-23r:3:w", + "tempora": "Feria VI after XXI Sunday after Pentecost", "title": "St. Anthony Mary Claret", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-24": { - "tempora": "Feria VI after XIX Sunday after Pentecost", + "2026-10-24": { + "id": "sancti:10-24:3:w", + "tempora": "Saturday after XXI Sunday after Pentecost", "title": "St. Raphael the Archangel", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-29": { - "tempora": "Feria IV after XX Sunday after Pentecost", + "2026-10-25": { + "id": "sancti:10-DU:1:w", + "tempora": "XXII Sunday after Pentecost", + "title": "Christ the King", + "rank": 1, + "colours": [ + "w" + ] + }, + "2026-10-26": { + "id": "tempora:Pent22-0:2:g", + "tempora": "Feria II after XXII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-27": { - "tempora": "Feria II after XX Sunday after Pentecost", + "2026-10-27": { + "id": "tempora:Pent22-0:2:g", + "tempora": "Feria III after XXII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-28": { - "tempora": "Feria III after XX Sunday after Pentecost", + "2026-10-28": { + "id": "sancti:10-28:2:r", + "tempora": "Feria IV after XXII Sunday after Pentecost", "title": "Sts. Simon & Jude", "rank": 2, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-10-31": { - "tempora": "Feria VI after XX Sunday after Pentecost", + "2026-10-29": { + "id": "tempora:Pent22-0:2:g", + "tempora": "Feria V after XXII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-01": { - "tempora": "Feria IV after XVI Sunday after Pentecost", + "2026-10-30": { + "id": "tempora:Pent22-0:2:g", + "tempora": "Feria VI after XXII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-11-01": { - "tempora": "Saturday after XX Sunday after Pentecost", + "2026-10-31": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XXII Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2026-11-01": { + "id": "sancti:11-01:1:w", + "tempora": "XXIII Sunday after Pentecost", "title": "All Saints", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-10-30": { - "tempora": "Feria V after XX Sunday after Pentecost", + "2026-11-02": { + "id": "sancti:11-02m1:1:b", + "tempora": "Feria II after XXIII Sunday after Pentecost", + "title": "Commemoration of All Souls", + "rank": 1, + "colours": [ + "b" + ] + }, + "2026-11-03": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria III after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-10-13": { - "tempora": "Feria II after XVIII Sunday after Pentecost", - "title": "St. Edward", + "2026-11-04": { + "id": "sancti:11-04:3:w", + "tempora": "Feria IV after XXIII Sunday after Pentecost", + "title": "St. Charles Borromeo", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-05": { - "tempora": "Feria IV after XXI Sunday after Pentecost", + "2026-11-05": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria V after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-11-02": { - "tempora": "", - "title": "XXI Sunday after Pentecost", - "rank": 2, - "colour": "g" - }, - "2025-11-07": { - "tempora": "Feria VI after XXI Sunday after Pentecost", + "2026-11-06": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria VI after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-11-06": { - "tempora": "Feria V after XXI Sunday after Pentecost", - "title": "Feria", + "2026-11-07": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XXIII Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-11-14": { - "tempora": "Feria VI after XXII Sunday after Pentecost", - "title": "St. Josaphat", + "2026-11-08": { + "id": "tempora:Epi5-0:2:g", + "tempora": "", + "title": "V Sunday after Epiphany", + "rank": 2, + "colours": [ + "g" + ] + }, + "2026-11-09": { + "id": "sancti:11-09:2:w", + "tempora": "Feria II after V Sunday after Epiphany", + "title": "Dedication of the Archbasilica of Our Holy Savior", + "rank": 2, + "colours": [ + "w" + ] + }, + "2026-11-10": { + "id": "sancti:11-10:3:w", + "tempora": "Feria III after V Sunday after Epiphany", + "title": "St. Andrew Avellino", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-12": { - "tempora": "Feria IV after XXII Sunday after Pentecost", + "2026-11-11": { + "id": "sancti:11-11:3:w", + "tempora": "Feria IV after V Sunday after Epiphany", + "title": "St. Martin of Tours", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-11-12": { + "id": "sancti:11-12:3:r", + "tempora": "Feria V after V Sunday after Epiphany", "title": "St. Martin I", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-11-16": { + "2026-11-13": { + "id": "tempora:Epi5-0:2:g", + "tempora": "Feria VI after V Sunday after Epiphany", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2026-11-14": { + "id": "sancti:11-14:3:w", + "tempora": "Saturday after V Sunday after Epiphany", + "title": "St. Josaphat", + "rank": 3, + "colours": [ + "w" + ] + }, + "2026-11-15": { + "id": "tempora:Epi6-0:2:g", "tempora": "", - "title": "XXIII Sunday after Pentecost", + "title": "VI Sunday after Epiphany", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-11-15": { - "tempora": "Saturday after XXII Sunday after Pentecost", - "title": "St. Albert the Great", + "2026-11-16": { + "id": "sancti:11-16:3:w", + "tempora": "Feria II after VI Sunday after Epiphany", + "title": "St. Gertrude the Great", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-13": { - "tempora": "Feria V after XXII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2026-11-17": { + "id": "sancti:11-17:3:w", + "tempora": "Feria III after VI Sunday after Epiphany", + "title": "St. Gregory the Wonderworker", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-11-11": { - "tempora": "Feria III after XXII Sunday after Pentecost", - "title": "St. Martin of Tours", + "2026-11-18": { + "id": "sancti:11-18r:3:w", + "tempora": "Feria IV after VI Sunday after Epiphany", + "title": "Dedication of the Basilicas of Sts. Peter & Paul", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-04": { - "tempora": "Feria III after XXI Sunday after Pentecost", - "title": "St. Charles Borromeo", + "2026-11-19": { + "id": "sancti:11-19:3:w", + "tempora": "Feria V after VI Sunday after Epiphany", + "title": "St. Elizabeth of Hungary", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-20": { - "tempora": "Feria V after XXIII Sunday after Pentecost", + "2026-11-20": { + "id": "sancti:11-20:3:w", + "tempora": "Feria VI after VI Sunday after Epiphany", "title": "St. Felix of Valois", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-10": { - "tempora": "Feria II after XXII Sunday after Pentecost", - "title": "St. Andrew Avellino", + "2026-11-21": { + "id": "sancti:11-21:3:w", + "tempora": "Saturday after VI Sunday after Epiphany", + "title": "Presentation of the Blessed Virgin Mary", "rank": 3, - "colour": "w" - }, - "2025-10-21": { - "tempora": "Feria III after XIX Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "w" + ] }, - "2025-11-23": { + "2026-11-22": { + "id": "tempora:Pent24-0:2:g", "tempora": "", "title": "XXIV Sunday after Pentecost", "rank": 2, - "colour": "g" - }, - "2025-10-25": { - "tempora": "Saturday after XIX Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "colours": [ + "g" + ] }, - "2025-11-17": { - "tempora": "Feria II after XXIII Sunday after Pentecost", - "title": "St. Gregory the Wonderworker", + "2026-11-23": { + "id": "sancti:11-23:3:r", + "tempora": "Feria II after XXIV Sunday after Pentecost", + "title": "St. Clement I", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2025-11-19": { - "tempora": "Feria IV after XXIII Sunday after Pentecost", - "title": "St. Elizabeth of Hungary", + "2026-11-24": { + "id": "sancti:11-24:3:w", + "tempora": "Feria III after XXIV Sunday after Pentecost", + "title": "St. John of the Cross", "rank": 3, - "colour": "w" - }, - "2025-11-09": { - "tempora": "XXII Sunday after Pentecost", - "title": "Dedication of the Archbasilica of Our Holy Savior", - "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-11-30": { - "tempora": "", - "title": "I Sunday of Advent", - "rank": 1, - "colour": "v" + "2026-11-25": { + "id": "sancti:11-25:3:r", + "tempora": "Feria IV after XXIV Sunday after Pentecost", + "title": "St. Catherine of Alexandria", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-11-27": { + "2026-11-26": { + "id": "sancti:11-26:3:w", "tempora": "Feria V after XXIV Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Sylvester", + "rank": 3, + "colours": [ + "w" + ] }, - "2025-11-28": { + "2026-11-27": { + "id": "tempora:Pent24-0:2:g", "tempora": "Feria VI after XXIV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2025-11-08": { - "tempora": "Saturday after XXI Sunday after Pentecost", + "2026-11-28": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XXIV Sunday after Pentecost", "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-01": { + "2026-11-29": { + "id": "tempora:Adv1-0:1:v", "tempora": "", - "title": "Feria II after I Sunday of Advent", - "rank": 3, - "colour": "v" + "title": "I Sunday of Advent", + "rank": 1, + "colours": [ + "v" + ] }, - "2025-11-22": { - "tempora": "Saturday after XXIII Sunday after Pentecost", - "title": "St. Cecilia", - "rank": 3, - "colour": "r" + "2026-11-30": { + "id": "sancti:11-30:2:r", + "tempora": "Feria II after I Sunday of Advent", + "title": "St. Andrew", + "rank": 2, + "colours": [ + "r" + ] }, - "2025-11-21": { - "tempora": "Feria VI after XXIII Sunday after Pentecost", - "title": "Presentation of the Blessed Virgin Mary", + "2026-12-01": { + "id": "tempora:Adv1-0:1:v", + "tempora": "", + "title": "Feria III after I Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-11-03": { - "tempora": "Feria II after XXI Sunday after Pentecost", - "title": "Commemoration of All Souls", - "rank": 1, - "colour": "b" + "2026-12-02": { + "id": "sancti:12-02:3:r", + "tempora": "Feria IV after I Sunday of Advent", + "title": "St. Vivian", + "rank": 3, + "colours": [ + "r" + ] }, - "2025-11-24": { - "tempora": "Feria II after XXIV Sunday after Pentecost", - "title": "St. John of the Cross", + "2026-12-03": { + "id": "sancti:12-03:3:w", + "tempora": "Feria V after I Sunday of Advent", + "title": "St. Francis Xavier", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-02": { - "tempora": "Feria III after I Sunday of Advent", - "title": "St. Vivian", + "2026-12-04": { + "id": "sancti:12-04:3:w", + "tempora": "Feria VI after I Sunday of Advent", + "title": "St. Peter Chrysologus", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-12-08": { - "tempora": "Feria II after II Sunday of Advent", - "title": "Immaculate Conception of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" + "2026-12-05": { + "id": "tempora:Adv1-0:1:v", + "tempora": "", + "title": "Sabbato after I Sunday of Advent", + "rank": 3, + "colours": [ + "v" + ] }, - "2025-12-07": { + "2026-12-06": { + "id": "tempora:Adv2-0:1:v", "tempora": "", "title": "II Sunday of Advent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-11-25": { - "tempora": "Feria III after XXIV Sunday after Pentecost", - "title": "St. Catherine of Alexandria", + "2026-12-07": { + "id": "sancti:12-07:3:w", + "tempora": "Feria II after II Sunday of Advent", + "title": "St. Ambrose", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2025-11-18": { - "tempora": "Feria III after XXIII Sunday after Pentecost", - "title": "Dedication of the Basilicas of Sts. Peter & Paul", - "rank": 3, - "colour": "w" + "2026-12-08": { + "id": "sancti:12-08:1:w", + "tempora": "Feria III after II Sunday of Advent", + "title": "Immaculate Conception of the Blessed Virgin Mary", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-12-09": { + "2026-12-09": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Feria III after II Sunday of Advent", - "rank": 3, - "colour": "v" - }, - "2025-12-03": { - "tempora": "Feria IV after I Sunday of Advent", - "title": "St. Francis Xavier", + "title": "Feria IV after II Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-12-12": { + "2026-12-10": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Feria VI after II Sunday of Advent", + "title": "Feria V after II Sunday of Advent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-12-04": { - "tempora": "Feria V after I Sunday of Advent", - "title": "St. Peter Chrysologus", + "2026-12-11": { + "id": "sancti:12-11:3:w", + "tempora": "Feria VI after II Sunday of Advent", + "title": "St. Damasus I", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-05": { + "2026-12-12": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Feria VI after I Sunday of Advent", - "rank": 3, - "colour": "v" - }, - "2025-12-06": { - "tempora": "Sabbato after I Sunday of Advent", - "title": "St. Nicholas", + "title": "Sabbato after II Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2025-12-14": { + "2026-12-13": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", "title": "III Sunday of Advent", "rank": 1, - "colour": "pv" + "colours": [ + "p", + "v" + ] }, - "2025-12-15": { + "2026-12-14": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", "title": "Feria II after III Sunday of Advent", "rank": 3, - "colour": "pv" + "colours": [ + "p", + "v" + ] }, - "2025-11-29": { - "tempora": "Saturday after XXIV Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" - }, - "2025-12-18": { + "2026-12-15": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", - "title": "Feria V after III Sunday of Advent", - "rank": 2, - "colour": "pv" - }, - "2025-12-11": { - "tempora": "Feria V after II Sunday of Advent", - "title": "St. Damasus I", + "title": "Feria III after III Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "p", + "v" + ] }, - "2025-12-25": { + "2026-12-16": { + "id": "tempora:Adv3-3:2:v", "tempora": "", - "title": "The Nativity of Our Lord", - "rank": 1, - "colour": "w" + "title": "Ember Wednesday of Advent", + "rank": 2, + "colours": [ + "v" + ] }, - "2025-12-19": { + "2026-12-17": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", - "title": "Ember Friday of Advent", + "title": "Feria V after III Sunday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "p", + "v" + ] }, - "2025-12-10": { + "2026-12-18": { + "id": "tempora:Adv3-5:2:v", "tempora": "", - "title": "Feria IV after II Sunday of Advent", - "rank": 3, - "colour": "v" + "title": "Ember Friday of Advent", + "rank": 2, + "colours": [ + "v" + ] }, - "2025-12-17": { + "2026-12-19": { + "id": "tempora:Adv3-6:2:v", "tempora": "", - "title": "Ember Wednesday of Advent", + "title": "Ember Saturday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-11-26": { - "tempora": "Feria IV after XXIV Sunday after Pentecost", - "title": "St. Sylvester", - "rank": 3, - "colour": "w" - }, - "2025-12-21": { + "2026-12-20": { + "id": "tempora:Adv4-0:1:v", "tempora": "", "title": "IV Sunday of Advent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] + }, + "2026-12-21": { + "id": "sancti:12-21:2:r", + "tempora": "Feria II after IV Sunday of Advent", + "title": "St. Thomas", + "rank": 2, + "colours": [ + "r" + ] }, - "2025-12-22": { + "2026-12-22": { + "id": "tempora:Adv4-0:1:v", "tempora": "", - "title": "Feria II after IV Sunday of Advent", + "title": "Feria III after IV Sunday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-12-24": { + "2026-12-23": { + "id": "tempora:Adv4-0:1:v", + "tempora": "", + "title": "Feria IV after IV Sunday of Advent", + "rank": 2, + "colours": [ + "v" + ] + }, + "2026-12-24": { + "id": "sancti:12-24:1:v", "tempora": "", "title": "Vigil of Christmas", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2025-12-13": { - "tempora": "Sabbato after II Sunday of Advent", - "title": "St. Lucy", - "rank": 3, - "colour": "r" + "2026-12-25": { + "id": "sancti:12-25m1:1:w", + "tempora": "", + "title": "The Nativity of Our Lord", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-12-23": { + "2026-12-26": { + "id": "sancti:12-26:2:r", "tempora": "", - "title": "Feria III after IV Sunday of Advent", + "title": "St. Stephen", "rank": 2, - "colour": "v" + "colours": [ + "r" + ] }, - "2025-12-16": { - "tempora": "Feria III after III Sunday of Advent", - "title": "St. Eusebius", - "rank": 3, - "colour": "r" - }, - "2025-12-30": { + "2026-12-27": { + "id": "tempora:Nat1-0:2:w", "tempora": "", - "title": "Feria in the Octave of Christmas", + "title": "Sunday in the Octave of Christmas", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-26": { + "2026-12-28": { + "id": "sancti:12-28:2:r", "tempora": "", - "title": "St. Stephen", + "title": "Holy Innocents", "rank": 2, - "colour": "r" + "colours": [ + "r" + ] }, - "2025-12-31": { + "2026-12-29": { + "id": "tempora:Nat1-1:2:w", "tempora": "", "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-29": { + "2026-12-30": { + "id": "tempora:Nat1-1:2:w", "tempora": "", "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-27": { + "2026-12-31": { + "id": "tempora:Nat1-1:2:w", "tempora": "", - "title": "St. John the Evangelist", + "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2025-12-20": { + "2027-01-01": { + "id": "sancti:01-01:1:w", "tempora": "", - "title": "Ember Saturday of Advent", - "rank": 2, - "colour": "v" + "title": "Octave Day of Christmas", + "rank": 1, + "colours": [ + "w" + ] }, - "2025-12-28": { + "2027-01-02": { + "id": "commune:C10b:4:w", "tempora": "", - "title": "Sunday in the Octave of Christmas", + "title": "II Mass of the B. V. M. – Vultum Tuum", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-01-03": { + "id": "tempora:Nat2-0:2:w", + "tempora": "", + "title": "Holy Name of Jesus", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-01": { + "2027-01-04": { + "id": "sancti:01-01:1:w", "tempora": "", - "title": "Octave Day of Christmas", - "rank": 1, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-01-02": { + "2027-01-05": { + "id": "sancti:01-01:1:w", "tempora": "", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-06": { + "2027-01-06": { + "id": "sancti:01-06:1:w", "tempora": "", "title": "Epiphany of the Lord", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-04": { + "2027-01-07": { + "id": "sancti:01-06:1:w", "tempora": "", - "title": "Holy Name of Jesus", - "rank": 2, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-01-07": { + "2027-01-08": { + "id": "sancti:01-06:1:w", "tempora": "", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-05": { + "2027-01-09": { + "id": "commune:C10b:4:w", "tempora": "", - "title": "Feria", + "title": "II Mass of the B. V. M. – Vultum Tuum", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-12": { + "2027-01-10": { + "id": "tempora:Epi1-0:2:w", + "tempora": "", + "title": "The Holy Family: Jesus, Mary & Joseph", + "rank": 2, + "colours": [ + "w" + ] + }, + "2027-01-11": { + "id": "tempora:Epi1-0a:2:w", "tempora": "Feria II after Epiphany", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-18": { - "tempora": "", - "title": "II Sunday after Epiphany", - "rank": 2, - "colour": "g" + "2027-01-12": { + "id": "tempora:Epi1-0a:2:w", + "tempora": "Feria III after Epiphany", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-01-11": { - "tempora": "", - "title": "The Holy Family: Jesus, Mary & Joseph", + "2027-01-13": { + "id": "sancti:01-13:2:w", + "tempora": "Feria IV after Epiphany", + "title": "Commemoration of the Baptism of the Lord", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-17": { - "tempora": "Saturday after Epiphany", - "title": "St. Anthony", + "2027-01-14": { + "id": "sancti:01-14:3:w", + "tempora": "Feria V after Epiphany", + "title": "St. Hilary", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-20": { - "tempora": "Feria III after II Sunday after Epiphany", - "title": "Sts. Fabian & Sebastian", + "2027-01-15": { + "id": "sancti:01-15:3:w", + "tempora": "Feria VI after Epiphany", + "title": "St. Paul, the First Hermit", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-01-21": { - "tempora": "Feria IV after II Sunday after Epiphany", - "title": "St. Agnes", + "2027-01-16": { + "id": "sancti:01-16:3:r", + "tempora": "Saturday after Epiphany", + "title": "St. Marcellus I", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-01-19": { + "2027-01-17": { + "id": "tempora:Epi2-0:2:g", + "tempora": "", + "title": "II Sunday after Epiphany", + "rank": 2, + "colours": [ + "g" + ] + }, + "2027-01-18": { + "id": "tempora:Epi2-0:2:g", "tempora": "Feria II after II Sunday after Epiphany", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-01-22": { + "2027-01-19": { + "id": "tempora:Epi2-0:2:g", + "tempora": "Feria III after II Sunday after Epiphany", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-01-20": { + "id": "sancti:01-20:3:r", + "tempora": "Feria IV after II Sunday after Epiphany", + "title": "Sts. Fabian & Sebastian", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-01-21": { + "id": "sancti:01-21:3:r", "tempora": "Feria V after II Sunday after Epiphany", + "title": "St. Agnes", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-01-22": { + "id": "sancti:01-22:3:r", + "tempora": "Feria VI after II Sunday after Epiphany", "title": "Sts. Vincent & Anastasius", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-01-25": { + "2027-01-23": { + "id": "sancti:01-23:3:w", + "tempora": "Saturday after II Sunday after Epiphany", + "title": "St. Raymond of Peñafort", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-01-24": { + "id": "tempora:Quadp1-0:2:v", "tempora": "", - "title": "III Sunday after Epiphany", + "title": "Septuagesima Sunday", "rank": 2, - "colour": "g" + "colours": [ + "v" + ] }, - "2026-01-26": { - "tempora": "Feria II after III Sunday after Epiphany", - "title": "St. Polycarp", + "2027-01-25": { + "id": "sancti:01-25r:3:w", + "tempora": "Feria II after Septuagesima", + "title": "Conversion of St. Paul", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-01-24": { - "tempora": "Saturday after II Sunday after Epiphany", - "title": "St. Timothy", + "2027-01-26": { + "id": "sancti:01-26:3:r", + "tempora": "Feria III after Septuagesima", + "title": "St. Polycarp", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-01-27": { - "tempora": "Feria III after III Sunday after Epiphany", + "2027-01-27": { + "id": "sancti:01-27:3:w", + "tempora": "Feria IV after Septuagesima", "title": "St. John Chrysostom", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-28": { - "tempora": "Feria IV after III Sunday after Epiphany", + "2027-01-28": { + "id": "sancti:01-28:3:w", + "tempora": "Feria V after Septuagesima", "title": "St. Peter Nolasco", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-29": { - "tempora": "Feria V after III Sunday after Epiphany", + "2027-01-29": { + "id": "sancti:01-29:3:w", + "tempora": "Feria VI after Septuagesima", "title": "St. Francis de Sales", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-31": { - "tempora": "Saturday after III Sunday after Epiphany", - "title": "St. John Bosco", - "rank": 3, - "colour": "w" - }, - "2026-01-23": { - "tempora": "Feria VI after II Sunday after Epiphany", - "title": "St. Raymond of Peñafort", + "2027-01-30": { + "id": "sancti:01-30:3:r", + "tempora": "Saturday after Septuagesima", + "title": "St. Martina", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-02-01": { + "2027-01-31": { + "id": "tempora:Quadp2-0:2:v", "tempora": "", - "title": "Septuagesima Sunday", - "rank": 2, - "colour": "v" - }, - "2026-01-13": { - "tempora": "Feria III after Epiphany", - "title": "Commemoration of the Baptism of the Lord", + "title": "Sexagesima Sunday", "rank": 2, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-01-30": { - "tempora": "Feria VI after III Sunday after Epiphany", - "title": "St. Martina", + "2027-02-01": { + "id": "sancti:02-01:3:r", + "tempora": "Feria II after Sexagesima", + "title": "St. Ignatius of Antioch", "rank": 3, - "colour": "r" - }, - "2026-02-03": { - "tempora": "Feria III after Septuagesima", - "title": "Feria", - "rank": 4, - "colour": "v" - }, - "2026-01-08": { - "tempora": "", - "title": "Feria", - "rank": 4, - "colour": "w" - }, - "2026-01-09": { - "tempora": "", - "title": "Feria", - "rank": 4, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-02-02": { - "tempora": "Feria II after Septuagesima", + "2027-02-02": { + "id": "sancti:02-02:2:w", + "tempora": "Feria III after Sexagesimæ", "title": "Purification of the Blessed Virgin Mary", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-10": { - "tempora": "", - "title": "II Mass of the B. V. M. – Vultum Tuum", - "rank": 4, - "colour": "w" - }, - "2026-01-03": { - "tempora": "", - "title": "II Mass of the B. V. M. – Vultum Tuum", + "2027-02-03": { + "id": "tempora:Quadp2-0:2:v", + "tempora": "Feria IV after Sexagesimæ", + "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-01-16": { - "tempora": "Feria VI after Epiphany", - "title": "St. Marcellus I", - "rank": 3, - "colour": "r" - }, - "2026-02-08": { - "tempora": "", - "title": "Sexagesima Sunday", - "rank": 2, - "colour": "v" - }, - "2026-02-07": { - "tempora": "Saturday after Septuagesima", - "title": "St. Romuald", - "rank": 3, - "colour": "w" - }, - "2026-02-10": { - "tempora": "Feria III after Sexagesimæ", - "title": "St. Scholastica", + "2027-02-04": { + "id": "sancti:02-04:3:w", + "tempora": "Feria V after Sexagesimæ", + "title": "St. Andrew Corsini", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-02-05": { - "tempora": "Feria V after Septuagesima", + "2027-02-05": { + "id": "sancti:02-05:3:r", + "tempora": "Feria VI after Sexagesimæ", "title": "St. Agatha", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-01-15": { - "tempora": "Feria V after Epiphany", - "title": "St. Paul, the First Hermit", + "2027-02-06": { + "id": "sancti:02-06:3:w", + "tempora": "Saturday after Sexagesimæ", + "title": "St. Titus", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-02-11": { - "tempora": "Feria IV after Sexagesimæ", - "title": "Our Lady of Lourdes", - "rank": 3, - "colour": "w" + "2027-02-07": { + "id": "tempora:Quadp3-0:2:v", + "tempora": "", + "title": "Quinquagesima Sunday", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-02-12": { - "tempora": "Feria V after Sexagesimæ", - "title": "Seven Holy Servite Founders", + "2027-02-08": { + "id": "sancti:02-08:3:w", + "tempora": "Feria II after Quinquagesima", + "title": "St. John of Matha", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-02-13": { - "tempora": "Feria VI after Sexagesimæ", - "title": "Feria", - "rank": 4, - "colour": "v" - }, - "2026-02-04": { - "tempora": "Feria IV after Septuagesima", - "title": "St. Andrew Corsini", + "2027-02-09": { + "id": "sancti:02-09:3:w", + "tempora": "Feria III after Quinquagesima", + "title": "St. Cyril of Alexandria", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-01-14": { - "tempora": "Feria IV after Epiphany", - "title": "St. Hilary", - "rank": 3, - "colour": "w" + "2027-02-10": { + "id": "tempora:Quadp3-3:1:v", + "tempora": "", + "title": "Ash Wednesday", + "rank": 1, + "colours": [ + "v" + ] }, - "2026-02-20": { + "2027-02-11": { + "id": "tempora:Quadp3-4:3:v", "tempora": "", - "title": "Feria VI after Ash Wednesday", + "title": "Feria V after Ash Wednesday", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-15": { + "2027-02-12": { + "id": "tempora:Quadp3-5:3:v", "tempora": "", - "title": "Quinquagesima Sunday", - "rank": 2, - "colour": "v" + "title": "Feria VI after Ash Wednesday", + "rank": 3, + "colours": [ + "v" + ] }, - "2026-02-19": { + "2027-02-13": { + "id": "tempora:Quadp3-6:3:v", "tempora": "", - "title": "Feria V after Ash Wednesday", + "title": "Saturday after Ash Wednesday", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-22": { + "2027-02-14": { + "id": "tempora:Quad1-0:1:v", "tempora": "", "title": "I Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-21": { + "2027-02-15": { + "id": "tempora:Quad1-1:3:v", "tempora": "", - "title": "Saturday after Ash Wednesday", + "title": "Feria II after the I Sunday of Lent", "rank": 3, - "colour": "v" - }, - "2026-02-17": { - "tempora": "Feria III after Quinquagesima", - "title": "Feria", - "rank": 4, - "colour": "v" - }, - "2026-02-16": { - "tempora": "Feria II after Quinquagesima", - "title": "Feria", - "rank": 4, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-06": { - "tempora": "Feria VI after Septuagesima", - "title": "St. Titus", + "2027-02-16": { + "id": "tempora:Quad1-2:3:v", + "tempora": "", + "title": "Feria III after the I Sunday of Lent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-02-25": { + "2027-02-17": { + "id": "tempora:Quad1-3:2:v", "tempora": "", "title": "Ember Wednesday of Lent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-18": { + "2027-02-18": { + "id": "tempora:Quad1-4:3:v", "tempora": "", - "title": "Ash Wednesday", - "rank": 1, - "colour": "v" + "title": "Feria V after the I Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2026-03-02": { + "2027-02-19": { + "id": "tempora:Quad1-5:2:v", "tempora": "", - "title": "Feria II after the II Sunday of Lent", - "rank": 3, - "colour": "v" + "title": "Ember Friday of Lent", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-03-01": { + "2027-02-20": { + "id": "tempora:Quad1-6:2:v", + "tempora": "", + "title": "Ember Saturday of Lent", + "rank": 2, + "colours": [ + "v" + ] + }, + "2027-02-21": { + "id": "tempora:Quad2-0:1:v", "tempora": "", "title": "II Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-26": { - "tempora": "", - "title": "Feria V after the I Sunday of Lent", - "rank": 3, - "colour": "v" + "2027-02-22": { + "id": "sancti:02-22:2:w", + "tempora": "Feria II after the II Sunday of Lent", + "title": "Chair of St. Peter", + "rank": 2, + "colours": [ + "w" + ] }, - "2026-03-03": { + "2027-02-23": { + "id": "tempora:Quad2-2:3:v", "tempora": "", "title": "Feria III after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-24": { - "tempora": "Feria III after the I Sunday of Lent", + "2027-02-24": { + "id": "sancti:02-24:2:r", + "tempora": "Feria IV after the II Sunday of Lent", "title": "St. Matthias", "rank": 2, - "colour": "r" - }, - "2026-02-14": { - "tempora": "Saturday after Sexagesimæ", - "title": "III Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-02-09": { - "tempora": "Feria II after Sexagesima", - "title": "St. Cyril of Alexandria", + "2027-02-25": { + "id": "tempora:Quad2-4:3:v", + "tempora": "", + "title": "Feria V after the II Sunday of Lent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-02-23": { + "2027-02-26": { + "id": "tempora:Quad2-5:3:v", "tempora": "", - "title": "Feria II after the I Sunday of Lent", + "title": "Feria VI after the II Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-02-27": { + "2027-02-27": { + "id": "tempora:Quad2-6:3:v", "tempora": "", - "title": "Ember Friday of Lent", - "rank": 2, - "colour": "v" + "title": "Saturday after the II Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] }, - "2026-03-08": { + "2027-02-28": { + "id": "tempora:Quad3-0:1:v", "tempora": "", "title": "III Sunday of Lent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-05": { + "2027-03-01": { + "id": "tempora:Quad3-1:3:v", "tempora": "", - "title": "Feria V after the II Sunday of Lent", + "title": "Feria II after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-11": { + "2027-03-02": { + "id": "tempora:Quad3-2:3:v", + "tempora": "", + "title": "Feria III after the III Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] + }, + "2027-03-03": { + "id": "tempora:Quad3-3:3:v", "tempora": "", "title": "Feria IV after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-13": { + "2027-03-04": { + "id": "tempora:Quad3-4:3:v", + "tempora": "", + "title": "Feria V after the III Sunday of Lent", + "rank": 3, + "colours": [ + "v" + ] + }, + "2027-03-05": { + "id": "tempora:Quad3-5:3:v", "tempora": "", "title": "Feria VI after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-14": { + "2027-03-06": { + "id": "tempora:Quad3-6:3:v", "tempora": "", "title": "Saturday after the III Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-15": { + "2027-03-07": { + "id": "tempora:Quad4-0:1:pv", "tempora": "", "title": "IV Sunday of Lent", "rank": 1, - "colour": "pv" + "colours": [ + "p", + "v" + ] }, - "2026-02-28": { - "tempora": "", - "title": "Ember Saturday of Lent", - "rank": 2, - "colour": "v" - }, - "2026-03-16": { + "2027-03-08": { + "id": "tempora:Quad4-1:3:v", "tempora": "", "title": "Feria II after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-12": { + "2027-03-09": { + "id": "tempora:Quad4-2:3:v", "tempora": "", - "title": "Feria V after the III Sunday of Lent", + "title": "Feria III after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-06": { + "2027-03-10": { + "id": "tempora:Quad4-3:3:v", "tempora": "", - "title": "Feria VI after the II Sunday of Lent", + "title": "Feria IV after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-10": { + "2027-03-11": { + "id": "tempora:Quad4-4:3:v", "tempora": "", - "title": "Feria III after the III Sunday of Lent", + "title": "Feria V after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-09": { + "2027-03-12": { + "id": "tempora:Quad4-5:3:v", "tempora": "", - "title": "Feria II after the III Sunday of Lent", + "title": "Feria VI after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-07": { + "2027-03-13": { + "id": "tempora:Quad4-6:3:v", "tempora": "", - "title": "Saturday after the II Sunday of Lent", + "title": "Saturday after the IV Sunday of Lent", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-22": { + "2027-03-14": { + "id": "tempora:Quad5-0:1:v", "tempora": "", "title": "Passion Sunday", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-20": { + "2027-03-15": { + "id": "tempora:Quad5-1:3:v", "tempora": "", - "title": "Feria VI after the IV Sunday of Lent", + "title": "Feria II of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-23": { + "2027-03-16": { + "id": "tempora:Quad5-2:3:v", "tempora": "", - "title": "Feria II of Passion Week", + "title": "Feria III of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-26": { + "2027-03-17": { + "id": "tempora:Quad5-3:3:v", "tempora": "", - "title": "Feria V of Passion Week", + "title": "Feria IV of Passion Week", "rank": 3, - "colour": "v" - }, - "2026-03-19": { - "tempora": "Feria V after the IV Sunday of Lent", - "title": "St. Joseph, Spouse of the Bl. Virgin Mary", - "rank": 1, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-03-24": { + "2027-03-18": { + "id": "tempora:Quad5-4:3:v", "tempora": "", - "title": "Feria III of Passion Week", + "title": "Feria V of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-27": { + "2027-03-19": { + "id": "tempora:Quad5-5Feria:3:v", "tempora": "", "title": "Feria VI of Passion Week", "rank": 3, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-03-30": { + "2027-03-20": { + "id": "tempora:Quad5-6:3:v", "tempora": "", - "title": "Feria II of Holy Week", - "rank": 1, - "colour": "v" - }, - "2026-03-21": { - "tempora": "", - "title": "Saturday after the IV Sunday of Lent", + "title": "Saturday of Passion Week", "rank": 3, - "colour": "v" - }, - "2026-03-25": { - "tempora": "Feria IV of Passion Week", - "title": "Annunciation of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-04-02": { + "2027-03-21": { + "id": "tempora:Quad6-0r:1:rv", "tempora": "", - "title": "Holy Thursday", + "title": "Palm Sunday", "rank": 1, - "colour": "w" + "colours": [ + "r", + "v" + ] }, - "2026-04-03": { + "2027-03-22": { + "id": "tempora:Quad6-1:1:v", "tempora": "", - "title": "Good Friday", + "title": "Feria II of Holy Week", "rank": 1, - "colour": "bv" + "colours": [ + "v" + ] }, - "2026-03-28": { + "2027-03-23": { + "id": "tempora:Quad6-2:1:v", "tempora": "", - "title": "Saturday of Passion Week", - "rank": 3, - "colour": "v" + "title": "Feria III of Holy Week", + "rank": 1, + "colours": [ + "v" + ] }, - "2026-03-18": { + "2027-03-24": { + "id": "tempora:Quad6-3:1:v", "tempora": "", - "title": "Feria IV after the IV Sunday of Lent", - "rank": 3, - "colour": "v" + "title": "Feria IV of Holy Week", + "rank": 1, + "colours": [ + "v" + ] }, - "2026-03-04": { + "2027-03-25": { + "id": "tempora:Quad6-4r:1:w", "tempora": "", - "title": "Feria IV after the II Sunday of Lent", - "rank": 3, - "colour": "v" + "title": "Holy Thursday", + "rank": 1, + "colours": [ + "w" + ] }, - "2026-03-17": { + "2027-03-26": { + "id": "tempora:Quad6-5r:1:bv", "tempora": "", - "title": "Feria III after the IV Sunday of Lent", - "rank": 3, - "colour": "v" + "title": "Good Friday", + "rank": 1, + "colours": [ + "b", + "v" + ] }, - "2026-04-04": { + "2027-03-27": { + "id": "tempora:Quad6-6r:1:vw", "tempora": "", "title": "Holy Saturday", "rank": 1, - "colour": "vw" + "colours": [ + "v", + "w" + ] }, - "2026-04-06": { + "2027-03-28": { + "id": "tempora:Pasc0-0:1:w", "tempora": "", - "title": "Monday in the Octave of Easter", + "title": "Easter Sunday", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-05": { + "2027-03-29": { + "id": "tempora:Pasc0-1:1:w", "tempora": "", - "title": "Easter Sunday", + "title": "Monday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-07": { + "2027-03-30": { + "id": "tempora:Pasc0-2:1:w", "tempora": "", "title": "Tuesday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-03-29": { + "2027-03-31": { + "id": "tempora:Pasc0-3:1:w", "tempora": "", - "title": "Palm Sunday", + "title": "Wednesday in the Octave of Easter", "rank": 1, - "colour": "rv" + "colours": [ + "w" + ] }, - "2026-04-09": { + "2027-04-01": { + "id": "tempora:Pasc0-4:1:w", "tempora": "", "title": "Thursday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-03-31": { + "2027-04-02": { + "id": "tempora:Pasc0-5:1:w", "tempora": "", - "title": "Feria III of Holy Week", + "title": "Friday in the Octave of Easter", "rank": 1, - "colour": "v" + "colours": [ + "w" + ] }, - "2026-04-08": { + "2027-04-03": { + "id": "tempora:Pasc0-6:1:w", "tempora": "", - "title": "Wednesday in the Octave of Easter", + "title": "Saturday in the Octave of Easter", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-10": { - "tempora": "", - "title": "Friday in the Octave of Easter", - "rank": 1, - "colour": "w" - }, - "2026-04-12": { + "2027-04-04": { + "id": "tempora:Pasc1-0:1:w", "tempora": "", "title": "Low Sunday", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-11": { - "tempora": "", - "title": "Saturday in the Octave of Easter", + "2027-04-05": { + "id": "sancti:03-25:1:w", + "tempora": "Monday after I Sunday after Easter", + "title": "Annunciation of the Blessed Virgin Mary", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-16": { - "tempora": "Thursday after I Sunday after Easter", + "2027-04-06": { + "id": "tempora:Pasc1-0:1:w", + "tempora": "Tuesday after I Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-15": { + "2027-04-07": { + "id": "tempora:Pasc1-0:1:w", "tempora": "Wednesday after I Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-19": { + "2027-04-08": { + "id": "tempora:Pasc1-0:1:w", + "tempora": "Thursday after I Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-09": { + "id": "tempora:Pasc1-0:1:w", + "tempora": "Friday after I Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-10": { + "id": "commune:C10Pasc:4:w", + "tempora": "Saturday after I Sunday after Easter", + "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-11": { + "id": "tempora:Pasc2-0:2:w", "tempora": "", "title": "II Sunday after Easter", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-13": { - "tempora": "Monday after I Sunday after Easter", - "title": "St. Hermenegild", - "rank": 3, - "colour": "r" - }, - "2026-04-20": { + "2027-04-12": { + "id": "tempora:Pasc2-0:2:w", "tempora": "Monday after II Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-01": { - "tempora": "", - "title": "Feria IV of Holy Week", - "rank": 1, - "colour": "v" - }, - "2026-04-14": { - "tempora": "Tuesday after I Sunday after Easter", - "title": "St. Justin", + "2027-04-13": { + "id": "sancti:04-13:3:r", + "tempora": "Tuesday after II Sunday after Easter", + "title": "St. Hermenegild", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-04-22": { + "2027-04-14": { + "id": "sancti:04-14:3:r", "tempora": "Wednesday after II Sunday after Easter", - "title": "Sts. Soter & Caius", + "title": "St. Justin", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-04-25": { + "2027-04-15": { + "id": "tempora:Pasc2-0:2:w", + "tempora": "Thursday after II Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-16": { + "id": "tempora:Pasc2-0:2:w", + "tempora": "Friday after II Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-17": { + "id": "commune:C10Pasc:4:w", "tempora": "Saturday after II Sunday after Easter", - "title": "St. Mark", - "rank": 2, - "colour": "r" + "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-04-26": { + "2027-04-18": { + "id": "tempora:Pasc3-0r:2:w", "tempora": "", "title": "III Sunday after Easter", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-28": { - "tempora": "Tuesday after III Sunday after Easter", - "title": "St. Paul of the Cross", - "rank": 3, - "colour": "w" - }, - "2026-04-17": { - "tempora": "Friday after I Sunday after Easter", + "2027-04-19": { + "id": "tempora:Pasc3-0r:2:w", + "tempora": "Monday after III Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" - }, - "2026-04-24": { - "tempora": "Friday after II Sunday after Easter", - "title": "St. Fidelis of Sigmaringen", - "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-04-23": { - "tempora": "Thursday after II Sunday after Easter", + "2027-04-20": { + "id": "tempora:Pasc3-0r:2:w", + "tempora": "Tuesday after III Sunday after Easter", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-21": { - "tempora": "Tuesday after II Sunday after Easter", + "2027-04-21": { + "id": "sancti:04-21:3:w", + "tempora": "Wednesday after III Sunday after Easter", "title": "St. Anselm", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-01": { - "tempora": "Friday after III Sunday after Easter", - "title": "St. Joseph the Workman", - "rank": 1, - "colour": "w" - }, - "2026-04-29": { - "tempora": "Wednesday after III Sunday after Easter", - "title": "St. Peter of Verona", + "2027-04-22": { + "id": "sancti:04-22:3:r", + "tempora": "Thursday after III Sunday after Easter", + "title": "Sts. Soter & Caius", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-02": { + "2027-04-23": { + "id": "tempora:Pasc3-0r:2:w", + "tempora": "Friday after III Sunday after Easter", + "title": "Feria", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-04-24": { + "id": "sancti:04-24:3:r", "tempora": "Saturday after III Sunday after Easter", - "title": "St. Athanasius", + "title": "St. Fidelis of Sigmaringen", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-05-03": { + "2027-04-25": { + "id": "tempora:Pasc4-0:2:w", "tempora": "", "title": "IV Sunday after Easter", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-04-30": { - "tempora": "Thursday after III Sunday after Easter", - "title": "St. Catherine of Siena", + "2027-04-26": { + "id": "sancti:04-26:3:r", + "tempora": "Monday after IV Sunday after Easter", + "title": "Sts. Cletus & Marcellinus", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-04-27": { - "tempora": "Monday after III Sunday after Easter", + "2027-04-27": { + "id": "sancti:04-27:3:w", + "tempora": "Tuesday after IV Sunday after Easter", "title": "St. Peter Canisius", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-10": { - "tempora": "", - "title": "V Sunday after Easter", - "rank": 2, - "colour": "w" + "2027-04-28": { + "id": "sancti:04-28:3:w", + "tempora": "Wednesday after IV Sunday after Easter", + "title": "St. Paul of the Cross", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-05-04": { - "tempora": "Monday after IV Sunday after Easter", - "title": "St. Monica", + "2027-04-29": { + "id": "sancti:04-29:3:r", + "tempora": "Thursday after IV Sunday after Easter", + "title": "St. Peter of Verona", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-05-08": { + "2027-04-30": { + "id": "sancti:04-30:3:w", "tempora": "Friday after IV Sunday after Easter", - "title": "Feria", - "rank": 4, - "colour": "w" + "title": "St. Catherine of Siena", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-04-18": { - "tempora": "Saturday after I Sunday after Easter", - "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2027-05-01": { + "id": "sancti:05-01r:1:w", + "tempora": "Saturday after IV Sunday after Easter", + "title": "St. Joseph the Workman", + "rank": 1, + "colours": [ + "w" + ] }, - "2026-05-06": { - "tempora": "Wednesday after IV Sunday after Easter", + "2027-05-02": { + "id": "tempora:Pasc5-0:2:w", + "tempora": "", + "title": "V Sunday after Easter", + "rank": 2, + "colours": [ + "w" + ] + }, + "2027-05-03": { + "id": "tempora:Pasc5-0:2:w", + "tempora": "The Minor Litanies – Rogations", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-05": { - "tempora": "Tuesday after IV Sunday after Easter", - "title": "St. Pius V", - "rank": 3, - "colour": "w" - }, - "2026-05-12": { + "2027-05-04": { + "id": "sancti:05-04:3:w", "tempora": "The Minor Litanies – Rogations", - "title": "Sts. Nereus, Achilleus, Domitilla, & Pancras", + "title": "St. Monica", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-05-11": { - "tempora": "The Minor Litanies – Rogations", - "title": "Sts. Philip & James", + "2027-05-05": { + "id": "tempora:Pasc5-3:2:w", + "tempora": "", + "title": "Vigil of the Ascension", "rank": 2, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-05-07": { - "tempora": "Thursday after IV Sunday after Easter", - "title": "St. Stanislaus", - "rank": 3, - "colour": "r" - }, - "2026-05-14": { + "2027-05-06": { + "id": "tempora:Pasc5-4:1:w", "tempora": "", "title": "Ascension of the Lord", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-17": { + "2027-05-07": { + "id": "sancti:05-07:3:r", + "tempora": "Feria VI after the Ascension", + "title": "St. Stanislaus", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-05-08": { + "id": "commune:C10Pasc:4:w", + "tempora": "Saturday after the Ascension", + "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-05-09": { + "id": "tempora:Pasc6-0:2:w", "tempora": "", "title": "Sunday after the Ascension", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-21": { - "tempora": "Feria V after the Ascension", - "title": "Feria", - "rank": 4, - "colour": "w" - }, - "2026-05-18": { + "2027-05-10": { + "id": "sancti:05-10:3:w", "tempora": "Feria II after the Ascension", - "title": "St. Venantius", + "title": "St. Antoninus", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-05-09": { - "tempora": "Saturday after IV Sunday after Easter", - "title": "St. Gregory of Nazianzen", + "2027-05-11": { + "id": "sancti:05-11r:2:r", + "tempora": "Feria III after the Ascension", + "title": "Sts. Philip & James", + "rank": 2, + "colours": [ + "r" + ] + }, + "2027-05-12": { + "id": "sancti:05-12:3:r", + "tempora": "Feria IV after the Ascension", + "title": "Sts. Nereus, Achilleus, Domitilla, & Pancras", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-05-23": { - "tempora": "", - "title": "Saturday after the Ascension", - "rank": 1, - "colour": "r" + "2027-05-13": { + "id": "sancti:05-13:3:w", + "tempora": "Feria V after the Ascension", + "title": "St. Robert Bellarmine", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-05-22": { + "2027-05-14": { + "id": "tempora:Pasc6-0:2:w", "tempora": "Feria VI after the Ascension", "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-05-24": { + "2027-05-15": { + "id": "tempora:Pasc6-6:1:r", "tempora": "", - "title": "Pentecost Sunday", + "title": "Saturday after the Ascension", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-26": { + "2027-05-16": { + "id": "tempora:Pasc7-0:1:r", "tempora": "", - "title": "Tuesday after Pentecost", + "title": "Pentecost Sunday", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-13": { - "tempora": "", - "title": "Vigil of the Ascension", - "rank": 2, - "colour": "w" - }, - "2026-05-25": { + "2027-05-17": { + "id": "tempora:Pasc7-1:1:r", "tempora": "", "title": "Monday after Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-15": { - "tempora": "Feria VI after the Ascension", - "title": "St. John Baptist de la Salle", - "rank": 3, - "colour": "w" - }, - "2026-05-28": { + "2027-05-18": { + "id": "tempora:Pasc7-2:1:r", "tempora": "", - "title": "Thursday after Pentecost", + "title": "Tuesday after Pentecost", "rank": 1, - "colour": "r" - }, - "2026-05-19": { - "tempora": "Feria III after the Ascension", - "title": "St. Peter Celestine", - "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-05-20": { - "tempora": "Feria IV after the Ascension", - "title": "St. Bernardine of Siena", - "rank": 3, - "colour": "w" - }, - "2026-05-27": { + "2027-05-19": { + "id": "tempora:Pasc7-3:1:r", "tempora": "", "title": "Ember Wednesday of Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-29": { + "2027-05-20": { + "id": "tempora:Pasc7-4:1:r", "tempora": "", - "title": "Ember Friday of Pentecost", + "title": "Thursday after Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-05-16": { - "tempora": "Saturday after the Ascension", - "title": "IV Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "2027-05-21": { + "id": "tempora:Pasc7-5:1:r", + "tempora": "", + "title": "Ember Friday of Pentecost", + "rank": 1, + "colours": [ + "r" + ] }, - "2026-05-30": { + "2027-05-22": { + "id": "tempora:Pasc7-6:1:r", "tempora": "", "title": "Ember Saturday of Pentecost", "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-06-03": { - "tempora": "Feria IV after I Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2027-05-23": { + "id": "tempora:Pent01-0r:1:w", + "tempora": "", + "title": "Trinity Sunday", + "rank": 1, + "colours": [ + "w" + ] }, - "2026-06-08": { - "tempora": "Feria II after II Sunday after Pentecost", + "2027-05-24": { + "id": "tempora:Pent01-0a:2:g", + "tempora": "Feria II after I Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-05": { - "tempora": "Feria V after I Sunday after Pentecost", - "title": "St. Boniface", + "2027-05-25": { + "id": "sancti:05-25:3:w", + "tempora": "Feria III after I Sunday after Pentecost", + "title": "St. Gregory VII", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-06-07": { - "tempora": "", - "title": "II Sunday after Pentecost", - "rank": 2, - "colour": "g" + "2027-05-26": { + "id": "sancti:05-26:3:w", + "tempora": "Feria IV after I Sunday after Pentecost", + "title": "St. Philip Neri", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-05-31": { + "2027-05-27": { + "id": "tempora:Pent01-4:1:w", "tempora": "", - "title": "Trinity Sunday", + "title": "Corpus Christi", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-11": { - "tempora": "Feria V after II Sunday after Pentecost", - "title": "St. Barnabas", + "2027-05-28": { + "id": "sancti:05-28:3:w", + "tempora": "Feria V after I Sunday after Pentecost", + "title": "St. Augustine of Canterbury", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-06-01": { - "tempora": "Feria II after I Sunday after Pentecost", + "2027-05-29": { + "id": "sancti:05-29:3:w", + "tempora": "Saturday after I Sunday after Pentecost", + "title": "St. Mary Magdalene de Pazzi", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-05-30": { + "id": "tempora:Pent02-0r:2:g", + "tempora": "", + "title": "II Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2027-05-31": { + "id": "sancti:05-31:2:w", + "tempora": "Feria II after II Sunday after Pentecost", + "title": "Queenship of the Blessed Virgin Mary", + "rank": 2, + "colours": [ + "w" + ] + }, + "2027-06-01": { + "id": "sancti:06-01:3:w", + "tempora": "Feria III after II Sunday after Pentecost", "title": "St. Angela Merici", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-10": { + "2027-06-02": { + "id": "tempora:Pent02-0r:2:g", "tempora": "Feria IV after II Sunday after Pentecost", - "title": "St. Margaret of Scotland", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-06-04": { + "2027-06-03": { + "id": "tempora:Pent02-0r:2:g", + "tempora": "Feria V after II Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-06-04": { + "id": "tempora:Pent02-5:1:w", "tempora": "", - "title": "Corpus Christi", + "title": "Sacred Heart of Jesus", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-14": { + "2027-06-05": { + "id": "sancti:06-05:3:r", + "tempora": "Saturday after II Sunday after Pentecost", + "title": "St. Boniface", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-06-06": { + "id": "tempora:Pent03-0r:2:g", "tempora": "", "title": "III Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-16": { + "2027-06-07": { + "id": "tempora:Pent03-0r:2:g", + "tempora": "Feria II after III Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-06-08": { + "id": "tempora:Pent03-0r:2:g", "tempora": "Feria III after III Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-02": { - "tempora": "Feria III after I Sunday after Pentecost", + "2027-06-09": { + "id": "tempora:Pent03-0r:2:g", + "tempora": "Feria IV after III Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-12": { - "tempora": "", - "title": "Sacred Heart of Jesus", - "rank": 1, - "colour": "w" + "2027-06-10": { + "id": "sancti:06-10:3:w", + "tempora": "Feria V after III Sunday after Pentecost", + "title": "St. Margaret of Scotland", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-06-21": { + "2027-06-11": { + "id": "sancti:06-11:3:r", + "tempora": "Feria VI after III Sunday after Pentecost", + "title": "St. Barnabas", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-06-12": { + "id": "sancti:06-12:3:r", + "tempora": "Saturday after III Sunday after Pentecost", + "title": "St. John of San Fecundo", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-06-13": { + "id": "tempora:Pent04-0:2:g", "tempora": "", "title": "IV Sunday after Pentecost", "rank": 2, - "colour": "g" - }, - "2026-06-09": { - "tempora": "Feria III after II Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-13": { - "tempora": "Saturday after II Sunday after Pentecost", - "title": "St. Anthony of Padua", + "2027-06-14": { + "id": "sancti:06-14:3:w", + "tempora": "Feria II after IV Sunday after Pentecost", + "title": "St. Basil the Great", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-23": { + "2027-06-15": { + "id": "tempora:Pent04-0:2:g", "tempora": "Feria III after IV Sunday after Pentecost", - "title": "Vigil of the Nativity of St. John the Baptist", - "rank": 2, - "colour": "v" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-06-15": { - "tempora": "Feria II after III Sunday after Pentecost", + "2027-06-16": { + "id": "tempora:Pent04-0:2:g", + "tempora": "Feria IV after IV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-06": { - "tempora": "Saturday after I Sunday after Pentecost", - "title": "St. Norbert", + "2027-06-17": { + "id": "sancti:06-17r:3:w", + "tempora": "Feria V after IV Sunday after Pentecost", + "title": "St. Gregory Barbarigo", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-22": { - "tempora": "Feria II after IV Sunday after Pentecost", - "title": "St. Paulinus of Nola", + "2027-06-18": { + "id": "sancti:06-18:3:r", + "tempora": "Feria VI after IV Sunday after Pentecost", + "title": "St. Ephrem of Syria", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-06-19": { - "tempora": "Feria VI after III Sunday after Pentecost", + "2027-06-19": { + "id": "sancti:06-19:3:r", + "tempora": "Saturday after IV Sunday after Pentecost", "title": "St. Julia of Falconieri", "rank": 3, - "colour": "r" - }, - "2026-07-01": { - "tempora": "Feria IV after V Sunday after Pentecost", - "title": "The Precious Blood of Our Lord Jesus Christ", - "rank": 1, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-07-02": { - "tempora": "Feria V after V Sunday after Pentecost", - "title": "Visitation of the Blessed Virgin Mary", + "2027-06-20": { + "id": "tempora:Pent05-0:2:g", + "tempora": "", + "title": "V Sunday after Pentecost", "rank": 2, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-07-03": { - "tempora": "Feria VI after V Sunday after Pentecost", - "title": "St. Irenaeus", + "2027-06-21": { + "id": "sancti:06-21:3:w", + "tempora": "Feria II after V Sunday after Pentecost", + "title": "St. Aloysius Gongzaga", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-06-24": { - "tempora": "Feria IV after IV Sunday after Pentecost", + "2027-06-22": { + "id": "sancti:06-22:3:w", + "tempora": "Feria III after V Sunday after Pentecost", + "title": "St. Paulinus of Nola", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-06-23": { + "id": "sancti:06-23:2:v", + "tempora": "Feria IV after V Sunday after Pentecost", + "title": "Vigil of the Nativity of St. John the Baptist", + "rank": 2, + "colours": [ + "v" + ] + }, + "2027-06-24": { + "id": "sancti:06-24:1:w", + "tempora": "Feria V after V Sunday after Pentecost", "title": "Nativity of St. John the Baptist", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-07-04": { + "2027-06-25": { + "id": "sancti:06-25:3:w", + "tempora": "Feria VI after V Sunday after Pentecost", + "title": "St. William", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-06-26": { + "id": "sancti:06-26:3:r", "tempora": "Saturday after V Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "title": "Sts. John & Paul", + "rank": 3, + "colours": [ + "r" + ] }, - "2026-07-05": { + "2027-06-27": { + "id": "tempora:Pent06-0:2:g", "tempora": "", "title": "VI Sunday after Pentecost", "rank": 2, - "colour": "g" - }, - "2026-07-07": { - "tempora": "Feria III after VI Sunday after Pentecost", - "title": "Sts. Cyril & Methodius", - "rank": 3, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-07-06": { + "2027-06-28": { + "id": "sancti:06-28r:2:v", "tempora": "Feria II after VI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "Vigil of Sts. Peter & Paul", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-07-08": { + "2027-06-29": { + "id": "sancti:06-29:1:r", + "tempora": "Feria III after VI Sunday after Pentecost", + "title": "Sts. Peter & Paul", + "rank": 1, + "colours": [ + "r" + ] + }, + "2027-06-30": { + "id": "sancti:06-30:3:r", "tempora": "Feria IV after VI Sunday after Pentecost", - "title": "St. Elizabeth of Portugal", + "title": "In Commemoratione Sancti Pauli Apostoli", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-07-09": { + "2027-07-01": { + "id": "sancti:07-01:1:r", "tempora": "Feria V after VI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "The Precious Blood of Our Lord Jesus Christ", + "rank": 1, + "colours": [ + "r" + ] }, - "2026-07-10": { + "2027-07-02": { + "id": "sancti:07-02:2:w", "tempora": "Feria VI after VI Sunday after Pentecost", - "title": "Seven Holy Brothers and Sts. Rufina & Secunda", - "rank": 3, - "colour": "r" - }, - "2026-06-26": { - "tempora": "Feria VI after IV Sunday after Pentecost", - "title": "Sts. John & Paul", - "rank": 3, - "colour": "r" + "title": "Visitation of the Blessed Virgin Mary", + "rank": 2, + "colours": [ + "w" + ] }, - "2026-07-11": { + "2027-07-03": { + "id": "sancti:07-03r:3:r", "tempora": "Saturday after VI Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "title": "St. Irenaeus", + "rank": 3, + "colours": [ + "r" + ] }, - "2026-07-12": { + "2027-07-04": { + "id": "tempora:Pent07-0:2:g", "tempora": "", "title": "VII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-07-13": { + "2027-07-05": { + "id": "sancti:07-05:3:w", "tempora": "Feria II after VII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Anthony Mary Zaccariah", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-07-14": { + "2027-07-06": { + "id": "tempora:Pent07-0:2:g", "tempora": "Feria III after VII Sunday after Pentecost", - "title": "St. Bonaventure", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-06-18": { - "tempora": "Feria V after III Sunday after Pentecost", - "title": "St. Ephrem of Syria", + "2027-07-07": { + "id": "sancti:07-07:3:w", + "tempora": "Feria IV after VII Sunday after Pentecost", + "title": "Sts. Cyril & Methodius", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-07-15": { - "tempora": "Feria IV after VII Sunday after Pentecost", - "title": "St. Henry the Emperor", + "2027-07-08": { + "id": "sancti:07-08:3:w", + "tempora": "Feria V after VII Sunday after Pentecost", + "title": "St. Elizabeth of Portugal", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-07-17": { + "2027-07-09": { + "id": "tempora:Pent07-0:2:g", "tempora": "Feria VI after VII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" - }, - "2026-07-16": { - "tempora": "Feria V after VII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-07-18": { + "2027-07-10": { + "id": "sancti:07-10:3:r", "tempora": "Saturday after VII Sunday after Pentecost", - "title": "Camillus de Lellis", + "title": "Seven Holy Brothers and Sts. Rufina & Secunda", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-07-19": { + "2027-07-11": { + "id": "tempora:Pent08-0:2:g", "tempora": "", "title": "VIII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-29": { - "tempora": "Feria II after V Sunday after Pentecost", - "title": "Sts. Peter & Paul", - "rank": 1, - "colour": "r" - }, - "2026-07-22": { - "tempora": "Feria IV after VIII Sunday after Pentecost", - "title": "St. Mary Magdalene", + "2027-07-12": { + "id": "sancti:07-12:3:r", + "tempora": "Feria II after VIII Sunday after Pentecost", + "title": "St. John Gualbert", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-07-21": { + "2027-07-13": { + "id": "tempora:Pent08-0:2:g", "tempora": "Feria III after VIII Sunday after Pentecost", - "title": "St. Laurence of Brindisi", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-07-14": { + "id": "sancti:07-14:3:w", + "tempora": "Feria IV after VIII Sunday after Pentecost", + "title": "St. Bonaventure", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-07-23": { + "2027-07-15": { + "id": "sancti:07-15:3:w", "tempora": "Feria V after VIII Sunday after Pentecost", - "title": "St. Apollinaris", + "title": "St. Henry the Emperor", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-07-24": { + "2027-07-16": { + "id": "tempora:Pent08-0:2:g", "tempora": "Feria VI after VIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-07-25": { + "2027-07-17": { + "id": "commune:C10t:4:w", "tempora": "Saturday after VIII Sunday after Pentecost", - "title": "St. James the Greater", - "rank": 2, - "colour": "r" + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-07-26": { + "2027-07-18": { + "id": "tempora:Pent09-0:2:g", "tempora": "", "title": "IX Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-07-27": { + "2027-07-19": { + "id": "sancti:07-19:3:w", "tempora": "Feria II after IX Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Vincent de Paul", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-07-28": { + "2027-07-20": { + "id": "sancti:07-20:3:r", "tempora": "Feria III after IX Sunday after Pentecost", - "title": "Sts. Nazarius & Celsus, St. Victor I & St. Innocent I", + "title": "St. Jerome Emiliani", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-07-29": { + "2027-07-21": { + "id": "sancti:07-21r:3:w", "tempora": "Feria IV after IX Sunday after Pentecost", - "title": "St. Martha", + "title": "St. Laurence of Brindisi", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-07-30": { + "2027-07-22": { + "id": "sancti:07-22:3:w", "tempora": "Feria V after IX Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Mary Magdalene", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-07-31": { + "2027-07-23": { + "id": "sancti:07-23:3:w", "tempora": "Feria VI after IX Sunday after Pentecost", - "title": "St. Ignatius Loyola", + "title": "St. Apollinaris", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-01": { + "2027-07-24": { + "id": "commune:C10t:4:w", "tempora": "Saturday after IX Sunday after Pentecost", "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-02": { + "2027-07-25": { + "id": "tempora:Pent10-0:2:g", "tempora": "", "title": "X Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-08-03": { + "2027-07-26": { + "id": "sancti:07-26:2:w", "tempora": "Feria II after X Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Anne, Mother of the Blessed Virgin", + "rank": 2, + "colours": [ + "w" + ] }, - "2026-08-04": { + "2027-07-27": { + "id": "tempora:Pent10-0:2:g", "tempora": "Feria III after X Sunday after Pentecost", - "title": "St. Dominic", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-08-05": { + "2027-07-28": { + "id": "sancti:07-28:3:r", "tempora": "Feria IV after X Sunday after Pentecost", - "title": "Dedication of the Basilica of St. Mary Major", + "title": "Sts. Nazarius & Celsus, St. Victor I & St. Innocent I", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-08-06": { + "2027-07-29": { + "id": "sancti:07-29:3:r", "tempora": "Feria V after X Sunday after Pentecost", - "title": "Transfiguration of Our Lord", - "rank": 2, - "colour": "w" - }, - "2026-06-17": { - "tempora": "Feria IV after III Sunday after Pentecost", - "title": "St. Gregory Barbarigo", + "title": "St. Martha", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-08-07": { + "2027-07-30": { + "id": "tempora:Pent10-0:2:g", "tempora": "Feria VI after X Sunday after Pentecost", - "title": "St. Cajetan", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-08-08": { + "2027-07-31": { + "id": "sancti:07-31:3:w", "tempora": "Saturday after X Sunday after Pentecost", - "title": "St. John Mary Vianney", + "title": "St. Ignatius Loyola", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-10": { - "tempora": "Feria II after XI Sunday after Pentecost", - "title": "St. Lawrence", + "2027-08-01": { + "id": "tempora:Pent11-0:2:g", + "tempora": "", + "title": "XI Sunday after Pentecost", "rank": 2, - "colour": "r" + "colours": [ + "g" + ] }, - "2026-08-09": { - "tempora": "XI Sunday after Pentecost", - "title": "Vigil of St. Lawrence", + "2027-08-02": { + "id": "sancti:08-02:3:r", + "tempora": "Feria II after XI Sunday after Pentecost", + "title": "St. Alphonsus Liguori", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-08-11": { + "2027-08-03": { + "id": "tempora:Pent11-0:2:g", "tempora": "Feria III after XI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-08-12": { + "2027-08-04": { + "id": "sancti:08-04:3:w", "tempora": "Feria IV after XI Sunday after Pentecost", - "title": "St. Clare", + "title": "St. Dominic", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-13": { + "2027-08-05": { + "id": "sancti:08-05:3:w", "tempora": "Feria V after XI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2026-08-16": { - "tempora": "", - "title": "XII Sunday after Pentecost", - "rank": 2, - "colour": "g" + "title": "Dedication of the Basilica of St. Mary Major", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-08-14": { + "2027-08-06": { + "id": "sancti:08-06:2:w", "tempora": "Feria VI after XI Sunday after Pentecost", - "title": "Vigil of the Assumption", + "title": "Transfiguration of Our Lord", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-15": { + "2027-08-07": { + "id": "sancti:08-07:3:w", "tempora": "Saturday after XI Sunday after Pentecost", - "title": "Assumption of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" + "title": "St. Cajetan", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-08-17": { + "2027-08-08": { + "id": "tempora:Pent12-0:2:g", + "tempora": "", + "title": "XII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2027-08-09": { + "id": "sancti:08-09t:3:r", "tempora": "Feria II after XII Sunday after Pentecost", - "title": "St. Hyacinth", + "title": "Vigil of St. Lawrence", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-08-18": { + "2027-08-10": { + "id": "sancti:08-10:2:r", "tempora": "Feria III after XII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Lawrence", + "rank": 2, + "colours": [ + "r" + ] }, - "2026-08-19": { + "2027-08-11": { + "id": "tempora:Pent12-0:2:g", "tempora": "Feria IV after XII Sunday after Pentecost", - "title": "St. John Eudes", - "rank": 3, - "colour": "w" - }, - "2026-06-25": { - "tempora": "Feria V after IV Sunday after Pentecost", - "title": "St. William", - "rank": 3, - "colour": "w" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-08-20": { + "2027-08-12": { + "id": "sancti:08-12:3:w", "tempora": "Feria V after XII Sunday after Pentecost", - "title": "St. Bernard of Clairvaux", + "title": "St. Clare", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-21": { + "2027-08-13": { + "id": "tempora:Pent12-0:2:g", "tempora": "Feria VI after XII Sunday after Pentecost", - "title": "St. Jane Frances de Chantal", - "rank": 3, - "colour": "w" - }, - "2026-08-23": { - "tempora": "", - "title": "XIII Sunday after Pentecost", - "rank": 2, - "colour": "g" + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-08-22": { + "2027-08-14": { + "id": "sancti:08-14:2:w", "tempora": "Saturday after XII Sunday after Pentecost", - "title": "Immaculate Heart of Mary", + "title": "Vigil of the Assumption", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-24": { + "2027-08-15": { + "id": "sancti:08-15:1:w", + "tempora": "XIII Sunday after Pentecost", + "title": "Assumption of the Blessed Virgin Mary", + "rank": 1, + "colours": [ + "w" + ] + }, + "2027-08-16": { + "id": "sancti:08-16:2:w", "tempora": "Feria II after XIII Sunday after Pentecost", - "title": "St. Bartholomew", + "title": "St. Joachim, Father of the Blessed Virgin", "rank": 2, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-08-25": { + "2027-08-17": { + "id": "sancti:08-17:3:w", "tempora": "Feria III after XIII Sunday after Pentecost", - "title": "St. Louis IX", + "title": "St. Hyacinth", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-26": { + "2027-08-18": { + "id": "tempora:Pent13-0:2:g", "tempora": "Feria IV after XIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-08-27": { + "2027-08-19": { + "id": "sancti:08-19:3:w", "tempora": "Feria V after XIII Sunday after Pentecost", - "title": "St. Joseph Calasance", + "title": "St. John Eudes", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-08-28": { + "2027-08-20": { + "id": "sancti:08-20:3:w", "tempora": "Feria VI after XIII Sunday after Pentecost", - "title": "St. Augustine", + "title": "St. Bernard of Clairvaux", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-08-29": { + "2027-08-21": { + "id": "sancti:08-21:3:w", "tempora": "Saturday after XIII Sunday after Pentecost", - "title": "Beheading of St. John the Baptist", + "title": "St. Jane Frances de Chantal", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-08-30": { + "2027-08-22": { + "id": "tempora:Pent14-0:2:g", "tempora": "", "title": "XIV Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-08-31": { + "2027-08-23": { + "id": "sancti:08-23:3:w", "tempora": "Feria II after XIV Sunday after Pentecost", - "title": "St. Raymond Nonnatus", + "title": "St. Philip Benizi", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-09-01": { + "2027-08-24": { + "id": "sancti:08-24:2:r", "tempora": "Feria III after XIV Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2026-06-28": { - "tempora": "", - "title": "V Sunday after Pentecost", + "title": "St. Bartholomew", "rank": 2, - "colour": "g" + "colours": [ + "r" + ] }, - "2026-09-07": { - "tempora": "Feria II after XV Sunday after Pentecost", + "2027-08-25": { + "id": "sancti:08-25:3:w", + "tempora": "Feria IV after XIV Sunday after Pentecost", + "title": "St. Louis IX", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-08-26": { + "id": "tempora:Pent14-0:2:g", + "tempora": "Feria V after XIV Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-09-04": { + "2027-08-27": { + "id": "sancti:08-27:3:w", "tempora": "Feria VI after XIV Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Joseph Calasance", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-09-06": { + "2027-08-28": { + "id": "sancti:08-28:3:r", + "tempora": "Saturday after XIV Sunday after Pentecost", + "title": "St. Augustine", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-08-29": { + "id": "tempora:Pent15-0:2:g", "tempora": "", "title": "XV Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-06-30": { - "tempora": "Feria III after V Sunday after Pentecost", - "title": "In Commemoratione Sancti Pauli Apostoli", + "2027-08-30": { + "id": "sancti:08-30:3:r", + "tempora": "Feria II after XV Sunday after Pentecost", + "title": "St. Rose of Lima", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-09-03": { - "tempora": "Feria V after XIV Sunday after Pentecost", - "title": "St. Pius X", + "2027-08-31": { + "id": "sancti:08-31:3:w", + "tempora": "Feria III after XV Sunday after Pentecost", + "title": "St. Raymond Nonnatus", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-09-13": { - "tempora": "", - "title": "XVI Sunday after Pentecost", - "rank": 2, - "colour": "g" - }, - "2026-09-14": { - "tempora": "Feria II after XVI Sunday after Pentecost", - "title": "Exaltation of the Holy Cross", - "rank": 2, - "colour": "r" + "2027-09-01": { + "id": "tempora:Pent15-0:2:g", + "tempora": "Feria IV after XV Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-09-10": { + "2027-09-02": { + "id": "sancti:09-02:3:w", "tempora": "Feria V after XV Sunday after Pentecost", - "title": "St. Nicholas of Tolentino", + "title": "St. Stephen of Hungary", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-09-02": { - "tempora": "Feria IV after XIV Sunday after Pentecost", - "title": "St. Stephen of Hungary", + "2027-09-03": { + "id": "sancti:09-03:3:w", + "tempora": "Feria VI after XV Sunday after Pentecost", + "title": "St. Pius X", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-06-27": { - "tempora": "Saturday after IV Sunday after Pentecost", + "2027-09-04": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XV Sunday after Pentecost", "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-07-20": { - "tempora": "Feria II after VIII Sunday after Pentecost", - "title": "St. Jerome Emiliani", - "rank": 3, - "colour": "r" - }, - "2026-09-08": { - "tempora": "Feria III after XV Sunday after Pentecost", - "title": "Nativity of the Blessed Virgin Mary", + "2027-09-05": { + "id": "tempora:Pent16-0:2:g", + "tempora": "", + "title": "XVI Sunday after Pentecost", "rank": 2, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-06-20": { - "tempora": "Saturday after III Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "2027-09-06": { + "id": "tempora:Pent16-0:2:g", + "tempora": "Feria II after XVI Sunday after Pentecost", + "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-09-09": { - "tempora": "Feria IV after XV Sunday after Pentecost", + "2027-09-07": { + "id": "tempora:Pent16-0:2:g", + "tempora": "Feria III after XVI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-09-11": { - "tempora": "Feria VI after XV Sunday after Pentecost", + "2027-09-08": { + "id": "sancti:09-08:2:w", + "tempora": "Feria IV after XVI Sunday after Pentecost", + "title": "Nativity of the Blessed Virgin Mary", + "rank": 2, + "colours": [ + "w" + ] + }, + "2027-09-09": { + "id": "tempora:Pent16-0:2:g", + "tempora": "Feria V after XVI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-09-12": { - "tempora": "Saturday after XV Sunday after Pentecost", - "title": "Most Holy Name of Mary", + "2027-09-10": { + "id": "sancti:09-10:3:w", + "tempora": "Feria VI after XVI Sunday after Pentecost", + "title": "St. Nicholas of Tolentino", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-09-19": { + "2027-09-11": { + "id": "commune:C10t:4:w", "tempora": "Saturday after XVI Sunday after Pentecost", - "title": "St. Januarius & Companions", - "rank": 3, - "colour": "r" + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-09-21": { + "2027-09-12": { + "id": "tempora:Pent17-0:2:g", + "tempora": "", + "title": "XVII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2027-09-13": { + "id": "tempora:Pent17-0:2:g", "tempora": "Feria II after XVII Sunday after Pentecost", - "title": "St. Matthew", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-09-14": { + "id": "sancti:09-14:2:r", + "tempora": "Feria III after XVII Sunday after Pentecost", + "title": "Exaltation of the Holy Cross", "rank": 2, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-09-20": { - "tempora": "", - "title": "XVII Sunday after Pentecost", + "2027-09-15": { + "id": "sancti:09-15:2:w", + "tempora": "Feria IV after XVII Sunday after Pentecost", + "title": "Seven Sorrows of the Blessed Virgin Mary", "rank": 2, - "colour": "g" + "colours": [ + "w" + ] }, - "2026-09-05": { - "tempora": "Saturday after XIV Sunday after Pentecost", - "title": "St. Lawrence Justinian", + "2027-09-16": { + "id": "sancti:09-16:3:r", + "tempora": "Feria V after XVII Sunday after Pentecost", + "title": "Sts. Cornelius & Cyprian", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-09-18": { - "tempora": "Feria VI after XVI Sunday after Pentecost", - "title": "St. Joseph of Cupertino", - "rank": 3, - "colour": "w" + "2027-09-17": { + "id": "tempora:Pent17-0:2:g", + "tempora": "Feria VI after XVII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-09-28": { - "tempora": "Feria II after XVIII Sunday after Pentecost", - "title": "St. Wenceslaus", + "2027-09-18": { + "id": "sancti:09-18:3:w", + "tempora": "Saturday after XVII Sunday after Pentecost", + "title": "St. Joseph of Cupertino", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-09-27": { + "2027-09-19": { + "id": "tempora:Pent18-0:2:g", "tempora": "", "title": "XVIII Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-09-25": { - "tempora": "", - "title": "Ember Friday of September", - "rank": 2, - "colour": "v" + "2027-09-20": { + "id": "tempora:Pent18-0:2:g", + "tempora": "Feria II after XVIII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-09-29": { + "2027-09-21": { + "id": "sancti:09-21:2:r", "tempora": "Feria III after XVIII Sunday after Pentecost", - "title": "Dedication of St. Michael the Archangel", - "rank": 1, - "colour": "w" - }, - "2026-09-15": { - "tempora": "Feria III after XVI Sunday after Pentecost", - "title": "Seven Sorrows of the Blessed Virgin Mary", + "title": "St. Matthew", "rank": 2, - "colour": "w" - }, - "2026-09-17": { - "tempora": "Feria V after XVI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "r" + ] }, - "2026-09-23": { + "2027-09-22": { + "id": "tempora:093-3:2:v", "tempora": "", "title": "Ember Wednesday of September", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-10-02": { - "tempora": "Feria VI after XVIII Sunday after Pentecost", - "title": "Holy Guardian Angels", - "rank": 3, - "colour": "w" - }, - "2026-10-03": { - "tempora": "Saturday after XVIII Sunday after Pentecost", - "title": "St. Theresa of the Infant Jesus", + "2027-09-23": { + "id": "sancti:09-23:3:r", + "tempora": "Feria V after XVIII Sunday after Pentecost", + "title": "St. Linus", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-10-04": { + "2027-09-24": { + "id": "tempora:093-5:2:v", "tempora": "", - "title": "XIX Sunday after Pentecost", + "title": "Ember Friday of September", "rank": 2, - "colour": "g" - }, - "2026-09-30": { - "tempora": "Feria IV after XVIII Sunday after Pentecost", - "title": "St. Jerome", - "rank": 3, - "colour": "w" - }, - "2026-10-05": { - "tempora": "Feria II after XIX Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "colours": [ + "v" + ] }, - "2026-09-24": { - "tempora": "Feria V after XVII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2027-09-25": { + "id": "tempora:093-6:2:v", + "tempora": "", + "title": "Ember Saturday of September", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-10-07": { - "tempora": "Feria IV after XIX Sunday after Pentecost", - "title": "Our Lady of the Rosary", + "2027-09-26": { + "id": "tempora:Pent19-0:2:g", + "tempora": "", + "title": "XIX Sunday after Pentecost", "rank": 2, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-10-09": { - "tempora": "Feria VI after XIX Sunday after Pentecost", - "title": "St. John Leonardi", + "2027-09-27": { + "id": "sancti:09-27:3:r", + "tempora": "Feria II after XIX Sunday after Pentecost", + "title": "Sts. Cosmas & Damian", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-10-06": { + "2027-09-28": { + "id": "sancti:09-28:3:r", "tempora": "Feria III after XIX Sunday after Pentecost", - "title": "St. Bruno", + "title": "St. Wenceslaus", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-10-10": { - "tempora": "Saturday after XIX Sunday after Pentecost", - "title": "St. Francis Borgia", + "2027-09-29": { + "id": "sancti:09-29:1:w", + "tempora": "Feria IV after XIX Sunday after Pentecost", + "title": "Dedication of St. Michael the Archangel", + "rank": 1, + "colours": [ + "w" + ] + }, + "2027-09-30": { + "id": "sancti:09-30:3:w", + "tempora": "Feria V after XIX Sunday after Pentecost", + "title": "St. Jerome", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-12": { - "tempora": "Feria II after XX Sunday after Pentecost", + "2027-10-01": { + "id": "tempora:Pent19-0:2:g", + "tempora": "Feria VI after XIX Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-10-08": { - "tempora": "Feria V after XIX Sunday after Pentecost", - "title": "St. Bridget of Sweden", + "2027-10-02": { + "id": "sancti:10-02:3:w", + "tempora": "Saturday after XIX Sunday after Pentecost", + "title": "Holy Guardian Angels", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-11": { + "2027-10-03": { + "id": "tempora:Pent20-0:2:g", "tempora": "", "title": "XX Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-09-26": { - "tempora": "", - "title": "Ember Saturday of September", - "rank": 2, - "colour": "v" - }, - "2026-10-16": { - "tempora": "Feria VI after XX Sunday after Pentecost", - "title": "St. Hedwig", - "rank": 3, - "colour": "w" - }, - "2026-10-19": { - "tempora": "Feria II after XXI Sunday after Pentecost", - "title": "St. Peter of Alcantara", + "2027-10-04": { + "id": "sancti:10-04:3:w", + "tempora": "Feria II after XX Sunday after Pentecost", + "title": "St. Francis of Assisi", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-17": { - "tempora": "Saturday after XX Sunday after Pentecost", - "title": "St. Margaret Mary Alacoque", - "rank": 3, - "colour": "w" + "2027-10-05": { + "id": "tempora:Pent20-0:2:g", + "tempora": "Feria III after XX Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-10-14": { + "2027-10-06": { + "id": "sancti:10-06:3:w", "tempora": "Feria IV after XX Sunday after Pentecost", - "title": "St. Callistus I", - "rank": 3, - "colour": "r" - }, - "2026-09-22": { - "tempora": "Feria III after XVII Sunday after Pentecost", - "title": "St. Thomas of Villanova", + "title": "St. Bruno", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-15": { + "2027-10-07": { + "id": "sancti:10-07:2:w", "tempora": "Feria V after XX Sunday after Pentecost", - "title": "St. Teresa of Avila", - "rank": 3, - "colour": "w" + "title": "Our Lady of the Rosary", + "rank": 2, + "colours": [ + "w" + ] }, - "2026-09-16": { - "tempora": "Feria IV after XVI Sunday after Pentecost", - "title": "Sts. Cornelius & Cyprian", + "2027-10-08": { + "id": "sancti:10-08:3:w", + "tempora": "Feria VI after XX Sunday after Pentecost", + "title": "St. Bridget of Sweden", "rank": 3, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-10-20": { - "tempora": "Feria III after XXI Sunday after Pentecost", - "title": "St. John Cantius", + "2027-10-09": { + "id": "sancti:10-09:3:w", + "tempora": "Saturday after XX Sunday after Pentecost", + "title": "St. John Leonardi", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-18": { + "2027-10-10": { + "id": "tempora:Pent21-0:2:g", "tempora": "", "title": "XXI Sunday after Pentecost", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-10-27": { - "tempora": "Feria III after XXII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2027-10-11": { + "id": "sancti:10-11:2:w", + "tempora": "Feria II after XXI Sunday after Pentecost", + "title": "Maternity of the Blessed Virgin Mary", + "rank": 2, + "colours": [ + "w" + ] }, - "2026-10-01": { - "tempora": "Feria V after XVIII Sunday after Pentecost", + "2027-10-12": { + "id": "tempora:Pent21-0:2:g", + "tempora": "Feria III after XXI Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-10-23": { - "tempora": "Feria VI after XXI Sunday after Pentecost", - "title": "St. Anthony Mary Claret", + "2027-10-13": { + "id": "sancti:10-13:3:w", + "tempora": "Feria IV after XXI Sunday after Pentecost", + "title": "St. Edward", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-22": { + "2027-10-14": { + "id": "sancti:10-14:3:r", "tempora": "Feria V after XXI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "title": "St. Callistus I", + "rank": 3, + "colours": [ + "r" + ] }, - "2026-10-24": { + "2027-10-15": { + "id": "sancti:10-15:3:w", + "tempora": "Feria VI after XXI Sunday after Pentecost", + "title": "St. Teresa of Avila", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-10-16": { + "id": "sancti:10-16:3:w", "tempora": "Saturday after XXI Sunday after Pentecost", - "title": "St. Raphael the Archangel", + "title": "St. Hedwig", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-25": { - "tempora": "XXII Sunday after Pentecost", - "title": "Christ the King", - "rank": 1, - "colour": "w" + "2027-10-17": { + "id": "tempora:Pent22-0:2:g", + "tempora": "", + "title": "XXII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2026-10-28": { - "tempora": "Feria IV after XXII Sunday after Pentecost", - "title": "Sts. Simon & Jude", + "2027-10-18": { + "id": "sancti:10-18:2:r", + "tempora": "Feria II after XXII Sunday after Pentecost", + "title": "St. Luke the Evangelist", "rank": 2, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-10-13": { - "tempora": "Feria III after XX Sunday after Pentecost", - "title": "St. Edward", + "2027-10-19": { + "id": "sancti:10-19:3:w", + "tempora": "Feria III after XXII Sunday after Pentecost", + "title": "St. Peter of Alcantara", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-30": { + "2027-10-20": { + "id": "sancti:10-20:3:w", + "tempora": "Feria IV after XXII Sunday after Pentecost", + "title": "St. John Cantius", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-10-21": { + "id": "tempora:Pent22-0:2:g", + "tempora": "Feria V after XXII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-10-22": { + "id": "tempora:Pent22-0:2:g", "tempora": "Feria VI after XXII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-10-29": { - "tempora": "Feria V after XXII Sunday after Pentecost", + "2027-10-23": { + "id": "sancti:10-23r:3:w", + "tempora": "Saturday after XXII Sunday after Pentecost", + "title": "St. Anthony Mary Claret", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-10-24": { + "id": "tempora:Pent23-0:2:g", + "tempora": "", + "title": "XXIII Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] + }, + "2027-10-25": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria II after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-11-03": { + "2027-10-26": { + "id": "tempora:Pent23-0:2:g", "tempora": "Feria III after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-11-05": { + "2027-10-27": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria IV after XXIII Sunday after Pentecost", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] + }, + "2027-10-28": { + "id": "sancti:10-28:2:r", "tempora": "Feria V after XXIII Sunday after Pentecost", + "title": "Sts. Simon & Jude", + "rank": 2, + "colours": [ + "r" + ] + }, + "2027-10-29": { + "id": "tempora:Pent23-0:2:g", + "tempora": "Feria VI after XXIII Sunday after Pentecost", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-11-01": { - "tempora": "XXIII Sunday after Pentecost", + "2027-10-30": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XXIII Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-10-31": { + "id": "sancti:10-DU:1:w", + "tempora": "IV Sunday after Epiphany", + "title": "Christ the King", + "rank": 1, + "colours": [ + "w" + ] + }, + "2027-11-01": { + "id": "sancti:11-01:1:w", + "tempora": "Feria II after IV Sunday after Epiphany", "title": "All Saints", "rank": 1, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-10-26": { - "tempora": "Feria II after XXII Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2027-11-02": { + "id": "sancti:11-02m1:1:b", + "tempora": "Feria III after IV Sunday after Epiphany", + "title": "Commemoration of All Souls", + "rank": 1, + "colours": [ + "b" + ] }, - "2026-11-06": { - "tempora": "Feria VI after XXIII Sunday after Pentecost", + "2027-11-03": { + "id": "tempora:Epi4-0:2:g", + "tempora": "Feria IV after IV Sunday after Epiphany", "title": "Feria", "rank": 4, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-11-14": { - "tempora": "Saturday after V Sunday after Epiphany", - "title": "St. Josaphat", + "2027-11-04": { + "id": "sancti:11-04:3:w", + "tempora": "Feria V after IV Sunday after Epiphany", + "title": "St. Charles Borromeo", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-12": { - "tempora": "Feria V after V Sunday after Epiphany", - "title": "St. Martin I", - "rank": 3, - "colour": "r" + "2027-11-05": { + "id": "tempora:Epi4-0:2:g", + "tempora": "Feria VI after IV Sunday after Epiphany", + "title": "Feria", + "rank": 4, + "colours": [ + "g" + ] }, - "2026-11-08": { + "2027-11-06": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after IV Sunday after Epiphany", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] + }, + "2027-11-07": { + "id": "tempora:Epi5-0:2:g", "tempora": "", "title": "V Sunday after Epiphany", "rank": 2, - "colour": "g" - }, - "2026-11-16": { - "tempora": "Feria II after VI Sunday after Epiphany", - "title": "St. Gertrude the Great", - "rank": 3, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-10-31": { - "tempora": "Saturday after XXII Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "2027-11-08": { + "id": "tempora:Epi5-0:2:g", + "tempora": "Feria II after V Sunday after Epiphany", + "title": "Feria", "rank": 4, - "colour": "w" + "colours": [ + "g" + ] }, - "2026-11-15": { - "tempora": "", - "title": "VI Sunday after Epiphany", + "2027-11-09": { + "id": "sancti:11-09:2:w", + "tempora": "Feria III after V Sunday after Epiphany", + "title": "Dedication of the Archbasilica of Our Holy Savior", "rank": 2, - "colour": "g" + "colours": [ + "w" + ] }, - "2026-11-11": { + "2027-11-10": { + "id": "sancti:11-10:3:w", "tempora": "Feria IV after V Sunday after Epiphany", + "title": "St. Andrew Avellino", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-11-11": { + "id": "sancti:11-11:3:w", + "tempora": "Feria V after V Sunday after Epiphany", "title": "St. Martin of Tours", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-13": { + "2027-11-12": { + "id": "sancti:11-12:3:r", "tempora": "Feria VI after V Sunday after Epiphany", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2026-11-04": { - "tempora": "Feria IV after XXIII Sunday after Pentecost", - "title": "St. Charles Borromeo", + "title": "St. Martin I", "rank": 3, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-10-21": { - "tempora": "Feria IV after XXI Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" - }, - "2026-11-07": { - "tempora": "Saturday after XXIII Sunday after Pentecost", + "2027-11-13": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after V Sunday after Epiphany", "title": "V Mass of the B. V. M. – Salve, Sancta Parens", "rank": 4, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-22": { + "2027-11-14": { + "id": "tempora:Epi6-0:2:g", "tempora": "", - "title": "XXIV Sunday after Pentecost", + "title": "VI Sunday after Epiphany", "rank": 2, - "colour": "g" + "colours": [ + "g" + ] }, - "2026-11-10": { - "tempora": "Feria III after V Sunday after Epiphany", - "title": "St. Andrew Avellino", + "2027-11-15": { + "id": "sancti:11-15:3:w", + "tempora": "Feria II after VI Sunday after Epiphany", + "title": "St. Albert the Great", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-20": { - "tempora": "Feria VI after VI Sunday after Epiphany", - "title": "St. Felix of Valois", + "2027-11-16": { + "id": "sancti:11-16:3:w", + "tempora": "Feria III after VI Sunday after Epiphany", + "title": "St. Gertrude the Great", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-19": { + "2027-11-17": { + "id": "sancti:11-17:3:w", + "tempora": "Feria IV after VI Sunday after Epiphany", + "title": "St. Gregory the Wonderworker", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-11-18": { + "id": "sancti:11-18r:3:w", "tempora": "Feria V after VI Sunday after Epiphany", + "title": "Dedication of the Basilicas of Sts. Peter & Paul", + "rank": 3, + "colours": [ + "w" + ] + }, + "2027-11-19": { + "id": "sancti:11-19:3:w", + "tempora": "Feria VI after VI Sunday after Epiphany", "title": "St. Elizabeth of Hungary", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-17": { - "tempora": "Feria III after VI Sunday after Epiphany", - "title": "St. Gregory the Wonderworker", + "2027-11-20": { + "id": "sancti:11-20:3:w", + "tempora": "Saturday after VI Sunday after Epiphany", + "title": "St. Felix of Valois", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-27": { - "tempora": "Feria VI after XXIV Sunday after Pentecost", - "title": "Feria", - "rank": 4, - "colour": "g" + "2027-11-21": { + "id": "tempora:Pent24-0:2:g", + "tempora": "", + "title": "XXIV Sunday after Pentecost", + "rank": 2, + "colours": [ + "g" + ] }, - "2026-11-23": { + "2027-11-22": { + "id": "sancti:11-22:3:r", "tempora": "Feria II after XXIV Sunday after Pentecost", - "title": "St. Clement I", + "title": "St. Cecilia", "rank": 3, - "colour": "r" + "colours": [ + "r" + ] }, - "2026-11-09": { - "tempora": "Feria II after V Sunday after Epiphany", - "title": "Dedication of the Archbasilica of Our Holy Savior", - "rank": 2, - "colour": "w" - }, - "2026-11-30": { - "tempora": "Feria II after I Sunday of Advent", - "title": "St. Andrew", - "rank": 2, - "colour": "r" + "2027-11-23": { + "id": "sancti:11-23:3:r", + "tempora": "Feria III after XXIV Sunday after Pentecost", + "title": "St. Clement I", + "rank": 3, + "colours": [ + "r" + ] }, - "2026-11-29": { - "tempora": "", - "title": "I Sunday of Advent", - "rank": 1, - "colour": "v" + "2027-11-24": { + "id": "sancti:11-24:3:w", + "tempora": "Feria IV after XXIV Sunday after Pentecost", + "title": "St. John of the Cross", + "rank": 3, + "colours": [ + "w" + ] }, - "2026-12-01": { - "tempora": "", - "title": "Feria III after I Sunday of Advent", + "2027-11-25": { + "id": "sancti:11-25:3:r", + "tempora": "Feria V after XXIV Sunday after Pentecost", + "title": "St. Catherine of Alexandria", "rank": 3, - "colour": "v" + "colours": [ + "r" + ] }, - "2026-11-21": { - "tempora": "Saturday after VI Sunday after Epiphany", - "title": "Presentation of the Blessed Virgin Mary", + "2027-11-26": { + "id": "sancti:11-26:3:w", + "tempora": "Feria VI after XXIV Sunday after Pentecost", + "title": "St. Sylvester", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-11-02": { - "tempora": "Feria II after XXIII Sunday after Pentecost", - "title": "Commemoration of All Souls", - "rank": 1, - "colour": "b" + "2027-11-27": { + "id": "commune:C10t:4:w", + "tempora": "Saturday after XXIV Sunday after Pentecost", + "title": "V Mass of the B. V. M. – Salve, Sancta Parens", + "rank": 4, + "colours": [ + "w" + ] }, - "2026-12-06": { + "2027-11-28": { + "id": "tempora:Adv1-0:1:v", "tempora": "", - "title": "II Sunday of Advent", + "title": "I Sunday of Advent", "rank": 1, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-11-25": { - "tempora": "Feria IV after XXIV Sunday after Pentecost", - "title": "St. Catherine of Alexandria", + "2027-11-29": { + "id": "tempora:Adv1-0:1:v", + "tempora": "", + "title": "Feria II after I Sunday of Advent", "rank": 3, - "colour": "r" + "colours": [ + "v" + ] }, - "2026-11-24": { - "tempora": "Feria III after XXIV Sunday after Pentecost", - "title": "St. John of the Cross", + "2027-11-30": { + "id": "sancti:11-30:2:r", + "tempora": "Feria III after I Sunday of Advent", + "title": "St. Andrew", + "rank": 2, + "colours": [ + "r" + ] + }, + "2027-12-01": { + "id": "tempora:Adv1-0:1:v", + "tempora": "", + "title": "Feria IV after I Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-12-02": { - "tempora": "Feria IV after I Sunday of Advent", + "2027-12-02": { + "id": "sancti:12-02:3:r", + "tempora": "Feria V after I Sunday of Advent", "title": "St. Vivian", "rank": 3, - "colour": "r" - }, - "2026-11-28": { - "tempora": "Saturday after XXIV Sunday after Pentecost", - "title": "V Mass of the B. V. M. – Salve, Sancta Parens", - "rank": 4, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-11-18": { - "tempora": "Feria IV after VI Sunday after Epiphany", - "title": "Dedication of the Basilicas of Sts. Peter & Paul", + "2027-12-03": { + "id": "sancti:12-03:3:w", + "tempora": "Feria VI after I Sunday of Advent", + "title": "St. Francis Xavier", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-12-03": { - "tempora": "Feria V after I Sunday of Advent", - "title": "St. Francis Xavier", + "2027-12-04": { + "id": "sancti:12-04:3:w", + "tempora": "Sabbato after I Sunday of Advent", + "title": "St. Peter Chrysologus", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-12-09": { + "2027-12-05": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Feria IV after II Sunday of Advent", + "title": "II Sunday of Advent", + "rank": 1, + "colours": [ + "v" + ] + }, + "2027-12-06": { + "id": "sancti:12-06:3:w", + "tempora": "Feria II after II Sunday of Advent", + "title": "St. Nicholas", "rank": 3, - "colour": "v" + "colours": [ + "w" + ] }, - "2026-12-08": { + "2027-12-07": { + "id": "sancti:12-07:3:w", "tempora": "Feria III after II Sunday of Advent", - "title": "Immaculate Conception of the Blessed Virgin Mary", - "rank": 1, - "colour": "w" - }, - "2026-12-12": { - "tempora": "", - "title": "Sabbato after II Sunday of Advent", + "title": "St. Ambrose", "rank": 3, - "colour": "v" + "colours": [ + "w" + ] }, - "2026-12-13": { - "tempora": "", - "title": "III Sunday of Advent", + "2027-12-08": { + "id": "sancti:12-08:1:w", + "tempora": "Feria IV after II Sunday of Advent", + "title": "Immaculate Conception of the Blessed Virgin Mary", "rank": 1, - "colour": "pv" + "colours": [ + "w" + ] }, - "2026-12-05": { + "2027-12-09": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Sabbato after I Sunday of Advent", - "rank": 3, - "colour": "v" - }, - "2026-12-04": { - "tempora": "Feria VI after I Sunday of Advent", - "title": "St. Peter Chrysologus", + "title": "Feria V after II Sunday of Advent", "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-12-14": { + "2027-12-10": { + "id": "tempora:Adv2-0:1:v", "tempora": "", - "title": "Feria II after III Sunday of Advent", + "title": "Feria VI after II Sunday of Advent", "rank": 3, - "colour": "pv" + "colours": [ + "v" + ] }, - "2026-12-11": { - "tempora": "Feria VI after II Sunday of Advent", + "2027-12-11": { + "id": "sancti:12-11:3:w", + "tempora": "Sabbato after II Sunday of Advent", "title": "St. Damasus I", "rank": 3, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-12-17": { + "2027-12-12": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", - "title": "Feria V after III Sunday of Advent", - "rank": 2, - "colour": "pv" + "title": "III Sunday of Advent", + "rank": 1, + "colours": [ + "p", + "v" + ] }, - "2026-12-15": { + "2027-12-13": { + "id": "sancti:12-13r:3:r", + "tempora": "Feria II after III Sunday of Advent", + "title": "St. Lucy", + "rank": 3, + "colours": [ + "r" + ] + }, + "2027-12-14": { + "id": "tempora:Adv3-0:1:pv", "tempora": "", "title": "Feria III after III Sunday of Advent", "rank": 3, - "colour": "pv" + "colours": [ + "p", + "v" + ] }, - "2026-12-10": { + "2027-12-15": { + "id": "tempora:Adv3-3:2:v", "tempora": "", - "title": "Feria V after II Sunday of Advent", + "title": "Ember Wednesday of Advent", + "rank": 2, + "colours": [ + "v" + ] + }, + "2027-12-16": { + "id": "sancti:12-16:3:r", + "tempora": "Feria V after III Sunday of Advent", + "title": "St. Eusebius", "rank": 3, - "colour": "v" + "colours": [ + "r" + ] }, - "2026-12-18": { + "2027-12-17": { + "id": "tempora:Adv3-5:2:v", "tempora": "", "title": "Ember Friday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-11-26": { - "tempora": "Feria V after XXIV Sunday after Pentecost", - "title": "St. Sylvester", - "rank": 3, - "colour": "w" + "2027-12-18": { + "id": "tempora:Adv3-6:2:v", + "tempora": "", + "title": "Ember Saturday of Advent", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-12-20": { + "2027-12-19": { + "id": "tempora:Adv4-0:1:v", "tempora": "", "title": "IV Sunday of Advent", "rank": 1, - "colour": "v" - }, - "2026-12-07": { - "tempora": "Feria II after II Sunday of Advent", - "title": "St. Ambrose", - "rank": 3, - "colour": "w" + "colours": [ + "v" + ] }, - "2026-12-24": { + "2027-12-20": { + "id": "tempora:Adv4-0:1:v", "tempora": "", - "title": "Vigil of Christmas", - "rank": 1, - "colour": "v" + "title": "Feria II after IV Sunday of Advent", + "rank": 2, + "colours": [ + "v" + ] }, - "2026-12-22": { - "tempora": "", - "title": "Feria III after IV Sunday of Advent", + "2027-12-21": { + "id": "sancti:12-21:2:r", + "tempora": "Feria III after IV Sunday of Advent", + "title": "St. Thomas", "rank": 2, - "colour": "v" + "colours": [ + "r" + ] }, - "2026-12-23": { + "2027-12-22": { + "id": "tempora:Adv4-0:1:v", "tempora": "", "title": "Feria IV after IV Sunday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-12-16": { + "2027-12-23": { + "id": "tempora:Adv4-0:1:v", "tempora": "", - "title": "Ember Wednesday of Advent", + "title": "Feria V after IV Sunday of Advent", "rank": 2, - "colour": "v" + "colours": [ + "v" + ] }, - "2026-12-21": { - "tempora": "Feria II after IV Sunday of Advent", - "title": "St. Thomas", - "rank": 2, - "colour": "r" + "2027-12-24": { + "id": "sancti:12-24:1:v", + "tempora": "", + "title": "Vigil of Christmas", + "rank": 1, + "colours": [ + "v" + ] }, - "2026-12-30": { + "2027-12-25": { + "id": "sancti:12-25m1:1:w", "tempora": "", - "title": "Feria in the Octave of Christmas", - "rank": 2, - "colour": "w" + "title": "The Nativity of Our Lord", + "rank": 1, + "colours": [ + "w" + ] }, - "2026-12-26": { + "2027-12-26": { + "id": "tempora:Nat1-0:2:w", "tempora": "", - "title": "St. Stephen", + "title": "Sunday in the Octave of Christmas", "rank": 2, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-12-28": { + "2027-12-27": { + "id": "sancti:12-27:2:w", "tempora": "", - "title": "Holy Innocents", + "title": "St. John the Evangelist", "rank": 2, - "colour": "r" + "colours": [ + "w" + ] }, - "2026-12-29": { + "2027-12-28": { + "id": "sancti:12-28:2:r", "tempora": "", - "title": "Feria in the Octave of Christmas", + "title": "Holy Innocents", "rank": 2, - "colour": "w" + "colours": [ + "r" + ] }, - "2026-12-31": { + "2027-12-29": { + "id": "tempora:Nat1-1:2:w", "tempora": "", "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "w" + "colours": [ + "w" + ] }, - "2026-12-19": { + "2027-12-30": { + "id": "tempora:Nat1-1:2:w", "tempora": "", - "title": "Ember Saturday of Advent", + "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "v" + "colours": [ + "w" + ] }, - "2026-12-27": { + "2027-12-31": { + "id": "tempora:Nat1-1:2:w", "tempora": "", - "title": "Sunday in the Octave of Christmas", + "title": "Feria in the Octave of Christmas", "rank": 2, - "colour": "w" - }, - "2026-12-25": { - "tempora": "", - "title": "The Nativity of Our Lord", - "rank": 1, - "colour": "w" + "colours": [ + "w" + ] } } diff --git a/scripts/build-oracle-ef.sh b/scripts/build-oracle-ef.sh index 2864551..32cb385 100755 --- a/scripts/build-oracle-ef.sh +++ b/scripts/build-oracle-ef.sh @@ -1,38 +1,42 @@ #!/usr/bin/env bash -# build-oracle-ef.sh — generate the EF (1962) regression oracle by fetching -# missalemeum's per-date proper API (the same source lectio's trad scraper uses, -# built on Divinum Officium data) for 2025-2026. +# build-oracle-ef.sh — build the EF (1962) regression oracle from the committed +# missalemeum snapshot (sources/snapshot.tar.gz, missalemeum/en/YYYY-MM-DD.json, +# 2026-01-01 .. 2027-12-31, 730 days), not a live fetch, so the oracle is +# reproducible offline and pinned to a known-good snapshot. # -# NOT run by `go test`. Requires network + curl + jq + GNU date. From repo root: +# Three things about this data that cost hours to learn (see oracle_ef_test.go): +# 1. info.id looks like "sancti:MM-DD:rank:colour", but its embedded rank is +# the rank of the PROPERS USED that day, not the day's own rank (e.g. +# 2026-01-02 is a class-4 feria whose id is "sancti:01-01:1:w" because it +# reuses the Circumcision's propers). Extracted here for provenance only +# -- never parse rank/colour out of it. Use info.rank/info.colors. +# 2. info.colors is an array; 14 of 730 days carry two values (Gaudete/ +# Laetare "pv", Palm Sunday "rv", Good Friday "bv", Holy Saturday "vw"). +# The Go test compares by membership, not equality. +# 3. A two-colour value on a weekday can be a proper-reuse artifact (a feria +# inside Gaudete/Laetare week reusing the Sunday's own propers) rather +# than a claim about that weekday's own colour. +# +# From repo root: # scripts/build-oracle-ef.sh # Writes internal/calendar/testdata/oracle-ef.json: -# { "YYYY-MM-DD": {"tempora": "...", "title": "...", "rank": N, "colour": "w"} } -# tempora is "" when missalemeum returns null (then the temporal identity is in -# title); the Go test derives the season from tempora-or-title. +# { "YYYY-MM-DD": {"id":"...", "tempora":"...", "title":"...", "rank":N, "colours":["w",...]} } set -euo pipefail out=internal/calendar/testdata/oracle-ef.json -mkdir -p "$(dirname "$out")" work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT -for y in 2025 2026; do - d="$y-01-01" - while [ "$(date -d "$d" +%Y)" = "$y" ]; do - echo "$d" - d=$(date -d "$d +1 day" +%F) - done -done > "$work/dates" +tar xzf sources/snapshot.tar.gz -C "$work" missalemeum/en -fetch() { - local d="$1" - local j - j=$(curl -sf --max-time 25 "https://www.missalemeum.com/en/api/v5/proper/$d" || true) - printf '%s' "$j" | jq -c --arg d "$d" \ - '{($d): (.[0].info | {id:(.id // ""), tempora:(.tempora // ""), title:.title, rank:.rank, colour:(.colors|join(""))})}' \ - 2>/dev/null || true -} -export -f fetch +jq -s ' + map({(.[0].info.date): { + id: (.[0].info.id // ""), + tempora: (.[0].info.tempora // ""), + title: .[0].info.title, + rank: .[0].info.rank, + colours: .[0].info.colors + }}) | add +' "$work"/missalemeum/en/*.json > "$out" -xargs -P 12 -I{} bash -c 'fetch "$@"' _ {} < "$work/dates" | jq -s 'add' > "$out" echo "wrote $out ($(jq 'length' "$out") days)" >&2 -rm -rf "$work" diff --git a/scripts/gen-sanctoral-ef.go b/scripts/gen-sanctoral-ef.go index e3ad18e..0a43869 100644 --- a/scripts/gen-sanctoral-ef.go +++ b/scripts/gen-sanctoral-ef.go @@ -10,8 +10,10 @@ // (Lectio) and Gospel (Evangelium) citations, plus any sancti co-celebrations // listed as commemorations. Several reference years are tried per date so a // saint whose date is a Sunday (or under a higher feast) in one year is still -// captured, observed with its own readings, from another. Existing Latin names -// in the file are preserved (missalemeum has no Latin titles). +// captured, observed with its own readings, from another. Existing +// non-English names (Polish, Latin, or any other language already present +// in the file) are preserved verbatim -- missalemeum supplies English +// titles only. // // One-time; requires network. Run from the repo root: // @@ -113,21 +115,83 @@ func rankOf(n int) calendar.Rank { // classOf marks the feasts of the Lord (class lord). A II class feast of the // Lord takes the place of a Sunday of the same class (1960 occurrence rules) — -// e.g. the Purification (Presentation, Feb 2), the Exaltation of the Holy Cross -// (Sep 14), the Dedication of the Lateran (Nov 9). Saint/BVM feasts of the same -// class are only commemorated on a Sunday, so they need no marker. +// e.g. the Exaltation of the Holy Cross (Sep 14), the Dedication of the +// Archbasilica (Nov 9), the Commemoration of the Baptism (Jan 13). Saint/BVM +// feasts of the same class are only commemorated on a Sunday, so they need no +// marker. +// +// Two substring checks were narrowed, and one is new, found by checking the +// calendarium's own verbatim titles (missale-romanum-1962.pdf) against what +// this function produced -- but "purification" is a THIRD, DELIBERATELY +// DIFFERENT case, kept matching rather than narrowed, and the reason is +// itself worth recording: +// +// - "purification" IS kept as a lord match, even though the calendarium's +// own title is "IN PURIFICATIONE B. MARIAE VIRG." (a feast of the BLESSED +// VIRGIN by name) -- a DECISION AGAINST that primary text, made on +// occurrence-behaviour evidence, not a reading of it, and recorded as +// such rather than dressed up as textually clean. +// +// The tag's actual job is not naming/colour categorisation: it exists +// solely to drive the occurrence rule that separates RG 91 entry 14 +// ("Festa Domini II classis" -- takes an occurring II-class Sunday's +// place outright) from entry 16 ("Festa II classis Ecclesiae universae, +// quae non [sunt Domini]" -- merely commemorated on one), entry 15 +// ("Dominicae II classis") sitting between the two. Checked live against +// missalemeum (this generator's own data source): the Purification +// takes a II-class Sunday's place OUTRIGHT, commemorations EMPTY +// (2014-02-02, 2020-02-02, 2025-02-02, 2031-02-02, 2042-02-02, all +// fetched independently) -- entry 14's pattern, not entry 16's (control: +// the Nativity of the BVM, an undisputed ordinary Marian feast, on a +// Sunday -- 2019-09-08 -- shows the SUNDAY observed, the feast merely +// commemorated, entry 16's own pattern). RG 112(b), "Officium, Missa aut +// commemoratio de dominica excludit commemorationem... de festo vel +// mysterio Domini, et vicissim" (a Sunday's office and a feast/mystery +// OF THE LORD mutually exclude each other as commemorations), backs the +// empty commemoration list independently of RG 91's table position. +// +// Genuine primary-text counter-evidence exists and is not discarded: +// RG 120(b), "Adhibetur color albus... b) B. Mariae Virg., etiam in +// benedictione et processione candelarum die 2 februarii" -- 2 February +// is filed under the WHITE-colour rule's "B. Mariae Virg." heading, +// kept separate there from 120(a)'s own "Domini" heading. Both textual +// tests available (the calendarium's title, RG 120's own taxonomy) +// point BVM; the occurrence-behaviour evidence points Domini. This is a +// live, acknowledged disagreement with the primary text on the +// strength of oracle evidence about what the day actually DOES, not a +// claim that the text is wrong or ambiguous. See +// internal/calendar/precedence_ef_repro_test.go's +// TestPurificationBeatsFebruarySunday for the fixture this rests on -- +// committed, not merely asserted, since the deciding years (2 February +// on a Sunday) fall outside this repo's own 2026-2027 oracle snapshot +// window. +// +// - "holy name" alone is ambiguous: it matches BOTH "Holy Name of Jesus" +// (a feast of the Lord) and "Most Holy Name of Mary"/"Holy Name of Mary" +// (a feast of the BVM, calendarium: "Sanctissimi Nominis Mariae") -- +// wrongly matching the latter too. Excluded whenever the title also +// names Mary. Unlike the Purification, this one is NOT contested: its +// occurrence behaviour matches the ordinary-BVM pattern too. +// +// - "baptism" is a new case: "Commemoration of the Baptism of the Lord" (13 +// January, calendarium: "IN COMMEMORATIONE BAPTISMATIS D. N. I. C.") did +// not match any existing case -- the HasSuffix check below requires "of +// OUR Lord", but this title's own wording is "of THE Lord" -- so it was +// missing the marker entirely. func classOf(en string) string { l := strings.ToLower(en) switch { case strings.Contains(l, "holy cross"), // Exaltation / Finding of the Holy Cross strings.Contains(l, "transfiguration"), - strings.Contains(l, "purification"), // the Presentation of the Lord + strings.Contains(l, "purification"), // the Presentation of the Lord -- occurrence-behaviour evidence, see doc comment strings.Contains(l, "precious blood"), - strings.Contains(l, "holy name"), + strings.Contains(l, "baptism"), + strings.Contains(l, "holy name") && !strings.Contains(l, "mary"), strings.Contains(l, "dedication of the archbasilica"), strings.Contains(l, "of our holy savior"), strings.Contains(l, "of our lord jesus"), - strings.HasSuffix(l, "of our lord"): + strings.HasSuffix(l, "of our lord"), + strings.HasSuffix(l, "of the lord"): return "lord" } return "" @@ -169,6 +233,19 @@ type mmDay struct { } `json:"sections"` } +// fetchOnce fetches one date's proper. KNOWN LIMITATION: missalemeum +// returns one array element PER MASS on a date with more than one (25 +// December: three, ids ...m1/...m2/...m3) and this reads only `data[0]`, +// the first -- so a commemoration attached specifically to a second or +// third Mass (the calendarium's own "In secunda Missa: Commemoratio..." +// pattern, e.g. St Anastasia on Christmas Day) is structurally invisible +// to every caller of this function, not just harvestDate's own use of it. +// See the PRIMARY-SOURCE NOTE above harvestDate for the fuller account -- +// in Anastasia's specific case this is moot (missalemeum's own +// "commemorations" list is empty on all three of the date's records, not +// just the first, so fixing this would not by itself recover her), but the +// limitation is real and would matter for any date whose SECOND or third +// Mass genuinely does carry a commemoration missalemeum's API records. func fetchOnce(date string) (*mmDay, error) { req, _ := http.NewRequest("GET", "https://www.missalemeum.com/en/api/v5/proper/"+date, nil) req.Header.Set("User-Agent", ua) @@ -200,9 +277,16 @@ func fetch(date string) (*mmDay, error) { } type entry struct { - slug, date, colour, class, en, la, first, gospel string - rank calendar.Rank - observed bool // has readings / reliable rank + slug, date, colour, class, en, first, gospel string + rank calendar.Rank + observed bool // has readings / reliable rank + // otherNames holds every "name.<lang>" field already present in the + // existing file for this slug, EXCLUDING "name.en" (English always + // comes fresh from missalemeum, in `en` above). Keyed by the full + // field name (e.g. "name.pl") so main() can emit it verbatim without + // hardcoding a language list -- see main()'s own preservedNames + // comment for why a hardcoded list is exactly the bug this fixes. + otherNames map[string]string } // idParts splits "sancti:MM-DD[sfx]:RANK:COLOUR" into rank word and colour word. @@ -215,6 +299,32 @@ func idParts(id string) (calendar.Rank, string) { return rankOf(n), colourOf(p[3]) } +// idHomeDate extracts the "MM-DD" home date embedded in a missalemeum +// info.id ("sancti:MM-DD[sfx]:RANK:COLOUR" -- sfx is an internal +// disambiguator missalemeum sometimes appends, e.g. "01-28t", "11-09cc", +// "11-02m1"; the first 5 characters are always the date). Returns "" if id +// is too short to contain one. +// +// This is the fix for a class of bug the slug-collision fix above (in +// main()) exposed rather than caused: a MOVABLE-transfer feast displayed on +// whatever civil date it actually landed on in a given reference year (St +// Joseph, 19 March, impeded by a Sunday of Lent and shown on the 20th; the +// Annunciation deferred past Holy Week; All Souls moved to the Monday when 2 +// November is a Sunday; even St Matthias' fixed 24 February shown on the +// 25th in a leap year) still carries its OWN proper date in info.id, not the +// civil date queried. Comparing the two lets harvestDate recognise "this is +// not really this date's own office" and skip it, instead of harvesting a +// phantom fixed-date entry at the transferred civil date -- confirmed +// live (`curl .../api/v5/proper/2023-03-20`): id "sancti:03-19:1:w" while +// the date queried is 2023-03-20. +func idHomeDate(id string) string { + p := strings.SplitN(id, ":", 2) + if len(p) < 2 || len(p[1]) < 5 { + return "" + } + return p[1][:5] +} + func readingsFrom(d *mmDay) (first, gospel string) { for _, s := range d.Sections { if len(s.Body) == 0 || len(s.Body[0]) == 0 { @@ -234,40 +344,246 @@ func readingsFrom(d *mmDay) (first, gospel string) { return } +// PRIMARY-SOURCE NOTE (found and corrected during review): of the three +// local scans this generator's citations are checked against +// (docs/research/*.pdf in the sibling colitur repo), ONE -- +// "1962-06-23,…LT.pdf", the Archivum Liturgicum ELECTRONIC TRANSCRIPTION -- +// silently drops vigil commemorations that the other two, PHOTOGRAPHIC +// scans of the actual 1962 Missale Romanum, both carry. Confirmed on four +// entries: 7 August (Donatus), 9 August (Romanus), 14 August (Eusebius), +// 25 December (Anastasia) -- all present in both photographic scans' +// calendarium AND their own Proprium Sanctorum text ("Et fit +// commemoratio S. Romani Mar-", "...S. Eusebii Con-", etc.), all silently +// absent from the transcription. A `knownSpuriousComm` exclusion list once +// stood here, built by checking ONLY the transcription and concluding two +// of these four ("Romanus", "Eusebius" on 14 August) were spurious -- WRONG, +// on evidence that itself was incomplete, not on a genuine absence. Treat +// the photographic scans as the primary source and the electronic +// transcription as a convenience index only; where they disagree, the scan +// wins. (14 August's "St. Eusebius, Conf." and 16 December's "St. Eusebius, +// Ep. et Mart." are two different people, both genuinely in the calendarium +// -- see slugOverride below, not a reason to drop either.) +// +// Of the four confirming examples above, three (Donatus, Romanus, Eusebius) +// are fixed by this generator as of this note. **25 December's Anastasia is +// NOT, and cannot be from this data source alone** -- a different, NOT +// generator-fixable limitation, recorded so the next person does not +// mistake her continued absence for an oversight of the fix above (she was +// also missing at the branch point, so this is not a regression either): +// the photographic scan places her "In secunda Missa: Commemoratio S. +// Anastasiae Mart." -- specifically the SECOND of Christmas Day's three +// Masses (missalemeum's own "2026-12-25" query independently confirmed to +// return exactly three records, ids ...m1/...m2/...m3). Two compounding +// problems, not one: fetchOnce (below) reads only `data[0]`, the FIRST +// Mass, so this harvester cannot structurally see a commemoration attached +// to a date's second or third Mass at all, for ANY date, not just this +// one -- but ALSO, checked directly (not merely inferred from the +// symptom), missalemeum's OWN "commemorations" list is empty on all THREE +// of the 25 December records, not just the first -- so even a fetchOnce +// rewritten to merge all of a date's Masses would still not recover her: +// missalemeum's own data lacks her here, the same "transcription-shaped" +// gap as Donatus/Romanus/Eusebius, just in the live API rather than the +// static PDF this time. Not fixed: no source this generator reads carries +// her. + +// slugOverride gives a proper, distinct slug to a small number of +// commemorations whose title slugifies IDENTICALLY to an unrelated feast on +// a different fixed date. Confirmed against the calendarium: 28 January's +// "St. Agnes" is the traditional SECOND commemoration of the 21 January +// feast (the same saint, repeated, not a coincidence); 14 May's "St. +// Boniface" is a different early martyr from 5 June's Boniface of Mainz, an +// entirely different person whose title happens to abbreviate to the same +// English string; 14 August's "St. Eusebius" (a Confessor, calendarium "S. +// Eusebii Conf.") is likewise a different person from 16 December's "St. +// Eusebius" (a Bishop and Martyr, calendarium "S. Eusebii Ep. et Mart."), +// both genuinely commemorated, missalemeum giving both the same bare +// English title. Keyed "MM-DD/original-slug" -> replacement slug. +var slugOverride = map[string]string{ + "01-28/agnes": "agnes-secundo", + "08-14/eusebius": "eusebius-confessor", + "05-14/boniface": "boniface-martyr", +} + +// refYearExplainsAbsence is a RANK-BLIND SAMPLING HEURISTIC, not a rubric +// evaluator: it does not know, and cannot know, the true class of the saint +// it is being asked about -- only whether the TEMPORAL day alone (no +// sanctoral data at all) on this one reference date looks privileged enough +// that a saint failing to win there is unsurprising. It reports true for: a +// Sunday or a named I/II-class feast, an Ember day, the late-Advent or +// Christmas-octave privilege (I or II class), or a Lent/Passiontide feria +// (III class, privileged per RG 109(e)). +// +// Two known imprecisions, recorded rather than silently accepted: +// +// - The Lent/Passiontide branch is privilege over an EQUAL-OR-LOWER-class +// candidate only -- RG 109(e) does not let a mere III-class feria beat a +// I- or II-class feast. Nothing in this codebase's actual data currently +// exercises that gap (every saint this heuristic has ever been asked +// about that is demoted throughout Lent is independently III class or +// lower, per the calendarium), but the function does not itself enforce +// it, so a future entry could reach it. +// - It is a proxy for "why was this saint never observed", not a citation. +// 17-31 December is excluded from ever trusting the id-derived rank +// below, REGARDLESS of what this heuristic would otherwise say -- +// covering BOTH of round 1's own late-Advent/Christmas-octave rank +// promotions, on two DIFFERENT strengths of evidence, recorded +// separately because they are not the same case: +// -- 26-31 December (RG 68(d)/(e), a positive citation): "die 29 +// decembris, fit commemoratio S. Thomae Episcopi et Mart.; die 31 +// decembris, fit commemoratio S. Silvestri I Papae et Conf." -- the +// calendarium names each a bare "Commemoratio" with NO class of its +// own, even though the DAY they fall on is II class (within the +// Nativity Octave). Two REAL entries (Thomas Becket, Silvester) are +// live here; see the call site's own comment. +// -- 17-23 December (RG 91 entry 18, a PRECAUTIONARY exclusion, not a +// positive citation): round 1 also promoted these late-Advent +// ferias from class-3 to class-2 (same lineage, same coupling +// shape as 26-31 December's own promotion). No live entry tests +// this range today -- the sole sanctoral entry there, `thomas` +// (21 December), is an OBSERVED class-2 feast reached via the +// harvestDate `obs` path, not this function's id-rank-trust path +// at all -- but unlike 26-31 December, there is no RG citation +// stating that a saint commemorated here has NO independent class; +// RG 91 entry 18 only ranks the FERIA, and (per defect 2's own +// finding) a genuine class-2 FEAST commemorated here would +// actually WIN against it (entry 16 above entry 18), so "the day +// is class-2" does not reliably explain a class-2 saint's absence +// the way it does for 26-31 December's own two named cases. +// Excluded anyway, on the side of the KNOWN-safe default +// (RankCommemoration) rather than risk repeating the identical +// failure shape the day this range's own first real entry arrives. +// +// This is also a warning about a structural hazard, not just a boundary +// fix: this function calls calendar.Compute, i.e. it reads the ENGINE's OWN +// computed temporal ranks to decide what DATA to generate. A change to +// temporal_ef.go's ranking (e.g. round 1's own 17-23/26-31 December +// promotions, RG 91 entry 18 / RG 67-68) can silently flip this function's +// verdict and rewrite generated data with no code change to this file at +// all -- confirmed by direct measurement, not just reasoned about: running +// this function's body against the branch-point engine versus the current +// one over the six reference years flips the verdict on 50 dates across +// exactly these 13 MM-DD values (12-17 through 12-23, 12-26 through +// 12-31), no others. Any future temporal_ef.go rank change should re-check +// this function's own boundary cases, not just its own tests. +// +// harvestDate keeps a saint's commemoration id rank ONLY if every reference +// year in which it was seen returned true here -- a single false (an +// unprivileged day, or the December exclusion) is enough to fall back to +// RankCommemoration, the safe default (see St Blaise, whose own +// commemoration id claims rank 4 and is still correctly overridden to +// RankCommemoration, proving the id's rank is a candidate, not a verdict -- +// see the call site's own comment). +func refYearExplainsAbsence(date time.Time) bool { + if date.Month() == time.December && date.Day() >= 17 && date.Day() <= 31 { + // RG 68(d)/(e) (26-31 Dec) and RG 91 entry 18 (17-23 Dec, + // precautionary): "die 29 decembris, fit commemoratio S. Thomae + // Episcopi et Mart.; die 31 decembris, fit commemoratio S. + // Silvestri I Papae et Conf." -- both named as a bare + // "Commemoratio", no class. See this function's own doc comment. + return false + } + sel := calendar.DefaultSelection() + sel.Form = "old" + day := calendar.Compute(date, sel, nil) + if day.Observed.Rank == calendar.RankClass1 || day.Observed.Rank == calendar.RankClass2 { + return true + } + return day.Season == calendar.Lent || day.Season == calendar.Passiontide +} + +// commTracker accumulates one commemoration slug's data across reference +// years: the entry itself (first sighting's title/colour/id-rank), and +// whether EVERY year it was seen in was "explained" by refYearExplainsAbsence. +type commTracker struct { + entry entry + allExplained bool +} + // harvestDate returns the observed sanctoral office for a fixed MM-DD (nil if // the date is always a feria/temporal) plus any sancti commemorations seen. +// +// Every one of the `years` reference years is scanned for BOTH the observed +// office and commemorations -- neither loop exits early on the first hit. +// Two real bugs lived in an earlier version that DID exit early: +// +// 1. Returning as soon as the FIRST reference year showed an observed +// office discarded every commemoration that only showed up in a LATER +// year (e.g. 9 November: 2025, the first year tried, happens to be the +// one year of six with no "St. Theodore" commemoration alongside the +// Dedication of the Archbasilica; a `return` there drops Theodore for +// good). +// 2. The tempFeastSkip/Christ-the-King check used to `return nil, comms` +// outright -- correct for tempFeastSkip's three permanently-fixed dates +// (every year behaves the same, so nothing is lost), but wrong for +// Christ the King, which occupies a given MM-DD only in the one +// reference year it happens to be the last Sunday of October (2025 for +// 26 October, in this generator's own reference years): returning +// immediately there discarded "St. Evaristus", visible only in the OTHER +// five years. `continue` fixes both: the loop keeps trying every +// remaining year regardless of what any single year showed. func harvestDate(mmdd string) (*entry, []entry) { - var comms []entry - seenComm := map[string]bool{} + commTrack := map[string]*commTracker{} + var obs *entry for _, y := range years { date := fmt.Sprintf("%04d-%s", y, mmdd) - if _, err := time.Parse("2006-01-02", date); err != nil { + refDate, err := time.Parse("2006-01-02", date) + if err != nil { continue // e.g. 02-29 in a common year } d, err := fetch(date) if err != nil { continue } + explained := refYearExplainsAbsence(refDate) for _, c := range d.Info.Commemorations { if !strings.HasPrefix(c.ID, "sancti:") || !isSaintTitle(c.Title) { continue } + if home := idHomeDate(c.ID); home != "" && home != mmdd { + continue // a transferred feast's commemoration, not a genuine one for THIS date + } slug := slugify(c.Title) - if slug == "" || seenComm[slug] { + if slug == "" { continue } - seenComm[slug] = true - _, col := idParts(c.ID) - // A saint never OBSERVED in any harvest year — only ever commemorated — - // is a commemoration in the 1962 universal calendar: it does NOT have - // its own Mass and yields to the ferial office (which is celebrated with - // the saint commemorated). Rank it RankCommemoration, not the id's class - // (missalemeum reuses class-3/4 for these), so a genuine IV class feast - // still outranks the feria while a commemoration does not. If the same - // slug is observed in another year, that observed entry supersedes this. - comms = append(comms, entry{slug: slug, date: mmdd, colour: col, en: c.Title, rank: calendar.RankCommemoration}) + if t, ok := commTrack[slug]; ok { + if !explained { + t.allExplained = false + } + continue // title/colour/id-rank already captured from the first sighting + } + // The COMMEMORATION object's own id is a BETTER rank signal than + // the DAY's own info.id (which names the rank of whatever + // propers are reused that day, not the commemorated saint's) -- + // but "better" is not "always correct": St Blaise's own + // commemoration id is "sancti:02-03:4:r" (rank 4), and he is + // still, correctly, ruled RankCommemoration below, because he + // has no independent Mass at all in the 1960 books, not because + // his id's rank is wrong. The id's rank is a CANDIDATE value, + // trusted only when refYearExplainsAbsence's heuristic finds no + // counter-evidence across every reference year this slug is + // seen -- see that function's own doc comment for what the + // heuristic actually checks and its known limits. + rank, col := idParts(c.ID) + commTrack[slug] = &commTracker{ + entry: entry{slug: slug, date: mmdd, colour: col, en: c.Title, rank: rank}, + allExplained: explained, + } + } + if obs != nil { + continue // already have an observed office; keep scanning other years for MORE commemorations } if strings.HasPrefix(d.Info.ID, "sancti:") && isSaintTitle(d.Info.Title) { + if home := idHomeDate(d.Info.ID); home != "" && home != mmdd { + // A movable-transfer feast displayed on today's civil date in + // THIS particular reference year (St Joseph pushed to the + // 20th; the Annunciation deferred past Holy Week; All Souls + // moved to the Monday; St Matthias shown on the 25th in a + // leap year) -- not a genuine fixed office for mmdd itself. + // See idHomeDate's own doc comment for the live-verified + // evidence. Try the next reference year instead. + continue + } // A few Lord's feasts live in missalemeum's sancti namespace but the // EF temporal engine already computes them (Nativity, Circumcision, // Epiphany); exclude them so they aren't duplicated in the sanctoral. @@ -278,26 +594,62 @@ func harvestDate(mmdd string) (*entry, []entry) { // Christ the King is movable (last Sunday of October) and computed // by the temporal engine; missalemeum files it under sancti, so it // would otherwise leak into the sanctoral at a spurious fixed date. - return nil, comms + // `continue`, not `return`: this disqualifies only THIS year's + // observed-office candidacy, not the whole date (see doc comment). + continue } first, gospel := readingsFrom(d) col := colourOf(strings.Join(d.Info.Colors, "")) - return &entry{ + obs = &entry{ slug: slugify(d.Info.Title), date: mmdd, colour: col, class: classOf(d.Info.Title), en: d.Info.Title, first: first, gospel: gospel, rank: rankOf(d.Info.Rank), observed: true, - }, comms + } + } + } + comms := make([]entry, 0, len(commTrack)) + for _, t := range commTrack { + e := t.entry + if !t.allExplained { + // At least one reference year showed this saint demoted even on + // an ordinary, unprivileged day -- genuinely commemoration-only + // (see refYearExplainsAbsence), not merely unlucky sampling. + e.rank = calendar.RankCommemoration } + comms = append(comms, e) } - return nil, comms + return obs, comms } func main() { - // Existing Latin names to preserve (missalemeum has no Latin titles). - la := map[string]string{} + // preservedNames holds every "name.<lang>" field already present in the + // existing file, keyed by slug then by the full field name -- EVERY + // language missalemeum does not itself supply (it has English titles + // only), not a hardcoded whitelist of one or two. A whitelist is + // exactly the bug this replaces: an earlier version of this generator + // preserved only name.la, and -- unnoticed, because the bootstrapped + // file has in fact never carried a name.la value at all, so that + // mechanism was silently inert from the start -- name.pl had no + // preservation mechanism whatsoever. A regeneration deleted all 322 + // Polish names outright (measured: name.pl 322 -> 0), reaching + // mobile.Day(date, "ef", version, "pl") -- a shipped dlectio entry + // point -- on the app's next build, with `naming.CelebrationName`'s own + // name[lang] -> name.en fallback silently substituting English and no + // error anywhere. Generalising to every "name.*" key except name.en + // (English is always freshly regenerated from missalemeum, the whole + // point of this tool) means a third, fourth, or Nth language added to + // the file later survives a regeneration without this function ever + // needing to change again. + preservedNames := map[string]map[string]string{} for slug, rc := range caldata.Tridentine().Cels { - if v := rc.Fields["name.la"]; v != "" { - la[slug] = v + for k, v := range rc.Fields { + if v == "" || !strings.HasPrefix(k, "name.") || k == "name.en" { + continue + } + if preservedNames[slug] == nil { + preservedNames[slug] = map[string]string{} + } + preservedNames[slug][k] = v } } @@ -331,11 +683,34 @@ func main() { entries := map[string]entry{} add := func(e entry) { if cur, ok := entries[e.slug]; ok { - if cur.observed && !e.observed { - return // don't let a commemoration downgrade an observed office - } - if cur.observed && e.observed { - return // first observed year wins + if cur.date == e.date { + // Same fixed date: this is the SAME feast, seen again in + // another reference year or pass -- the existing dedup rules + // apply (an observed office is never downgraded by a + // commemoration; the first observed year wins). + if cur.observed && !e.observed { + return + } + if cur.observed && e.observed { + return + } + } else { + // A DIFFERENT fixed date slugified to the identical string + // (e.g. "St. Boniface" on both 14 May and 5 June, or "St. + // Agnes" on both 21 and 28 January) -- two distinct + // celebrations, not the same one recurring. The map is keyed + // by slug, so silently keeping the first and dropping the + // second here is exactly how St Agnes secundo (28 Jan), St + // Boniface Martyr (14 May), and their like went missing + // before this fix. Disambiguate instead of dropping. + if ov, ok := slugOverride[e.date+"/"+e.slug]; ok { + e.slug = ov + } else { + e.slug = e.slug + "-" + strings.ReplaceAll(e.date, "-", "") + } + if _, stillCollides := entries[e.slug]; stillCollides { + return // extremely unlikely second collision; drop rather than clobber + } } } entries[e.slug] = e @@ -347,17 +722,13 @@ func main() { } for _, r := range results { // commemorations after, so observed offices win for _, c := range r.comms { - if _, ok := entries[c.slug]; !ok { - add(c) - } + add(c) } } es := make([]entry, 0, len(entries)) for _, e := range entries { - if l := la[e.slug]; l != "" { - e.la = l - } + e.otherNames = preservedNames[e.slug] es = append(es, e) } sort.Slice(es, func(i, j int) bool { @@ -374,7 +745,9 @@ func main() { b.WriteString("; by internal/calendar (temporalEF) and is NOT listed here.\n") b.WriteString("; Ranks use the 1960 Code of Rubrics: class-1..class-4.\n") b.WriteString("; Generated by scripts/gen-sanctoral-ef.go from missalemeum (Divinum Officium 1962\n") - b.WriteString("; data). Latin names are hand-curated where present. See NOTICE.\n\n") + b.WriteString("; data). name.en is always regenerated fresh from missalemeum; every other\n") + b.WriteString("; name.<lang> (missalemeum supplies English only) is preserved verbatim from\n") + b.WriteString("; whatever this file already carried before regeneration. See NOTICE.\n\n") b.WriteString("[layer]\nid = tridentine\nname = General Roman Calendar of 1962\ntype = universal\n") for _, e := range es { fmt.Fprintf(&b, "\n[%s]\ndate = %s\nrank = %s\ncolour = %s\n", e.slug, e.date, e.rank, e.colour) @@ -382,8 +755,13 @@ func main() { fmt.Fprintf(&b, "class = %s\n", e.class) } fmt.Fprintf(&b, "name.en = %s\n", e.en) - if e.la != "" { - fmt.Fprintf(&b, "name.la = %s\n", e.la) + otherKeys := make([]string, 0, len(e.otherNames)) + for k := range e.otherNames { + otherKeys = append(otherKeys, k) + } + sort.Strings(otherKeys) // deterministic output regardless of map iteration order + for _, k := range otherKeys { + fmt.Fprintf(&b, "%s = %s\n", k, e.otherNames[k]) } if e.first != "" { fmt.Fprintf(&b, "reading.first = %s\n", e.first) |
