aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/calendar/temporal_ef.go26
-rw-r--r--internal/calendar/temporal_ef_test.go44
2 files changed, 70 insertions, 0 deletions
diff --git a/internal/calendar/temporal_ef.go b/internal/calendar/temporal_ef.go
index 26ad930..7d31b8b 100644
--- a/internal/calendar/temporal_ef.go
+++ b/internal/calendar/temporal_ef.go
@@ -276,6 +276,32 @@ func temporalEF(date time.Time) temporalDay {
// Unique ferial slug (season-week-weekday) so proper ferias (Lent, Advent,
// Holy Week, Ember days) can key their own readings; green-season ferias
// simply have no lectionary entry and fall back to the Sunday.
+ // RG 78 (Caput IX, "De sancta Maria in sabbato"): "In sabbatis, in quibus
+ // occurrit Officium de feria IV classis, fit de sancta Maria in sabbato."
+ // On a Saturday whose office would otherwise be a IV-class feria, the
+ // office is the votive Office of Our Lady, and it is white -- RG 431(e)
+ // classes that Mass as "Missa votiva IV classis ... de B. Maria Virg.",
+ // RG 121(a) gives a votive Mass the colour of the feast-type it answers
+ // to, and RG 120(b) makes feasts of the BVM white.
+ //
+ // The protasis is "a IV-class feria", which by this point in the function
+ // is exactly what rank still being RankClass4 means: every branch above
+ // has already promoted Advent, Lent, Passiontide, the Ember days, the
+ // privileged ferias and the Christmas octave out of it. Nothing further
+ // needs testing.
+ //
+ // The SLUG IS DELIBERATELY UNCHANGED. colitur, which has built this office
+ // since its v0.3.0, does the same and for a reason worth repeating: a
+ // bespoke slug would recur many times a year and break the "one slug per
+ // liturgical year" invariant, and the day's readings are selected by the
+ // Mass formulary rather than by the slug. Only the colour moves here.
+ //
+ // This is the temporal office only. If a sanctoral feast outranks the
+ // IV-class Saturday it wins as before and brings its own colour, exactly
+ // as it did when this day was a plain green feria.
+ if rank == RankClass4 && date.Weekday() == time.Saturday {
+ col = White
+ }
return efCel(season, "ef-"+string(slugSeason)+"-"+strconv.Itoa(week)+"-"+weekdayLower(date), col, rank, week)
}
diff --git a/internal/calendar/temporal_ef_test.go b/internal/calendar/temporal_ef_test.go
index a7fa8b0..1290a59 100644
--- a/internal/calendar/temporal_ef_test.go
+++ b/internal/calendar/temporal_ef_test.go
@@ -1,6 +1,7 @@
package calendar
import (
+ "strings"
"testing"
"time"
)
@@ -256,3 +257,46 @@ func TestTemporalEFEpiphanyWeekAnchor(t *testing.T) {
y, anchor.Format("2006-01-02"), got)
}
}
+
+// TestTemporalEFBVMSaturday pins RG 78, the votive Office of Our Lady on
+// Saturday: "In sabbatis, in quibus occurrit Officium de feria IV classis, fit
+// de sancta Maria in sabbato." A Saturday whose office would otherwise be a
+// IV-class feria keeps Our Lady's office instead, and it is white.
+//
+// Two things are asserted in opposite directions on purpose. The office
+// applies only where the feria really is IV class, so a Saturday in Lent or
+// Advent -- III class ferias, violet -- must NOT turn white; and the slug must
+// NOT change, because the day's readings are still the feria's and a bespoke
+// slug would recur many times a year.
+func TestTemporalEFBVMSaturday(t *testing.T) {
+ // Ordinary per-annum Saturdays: IV class, so Our Lady's office, white.
+ for _, day := range []string{"2026-06-20", "2026-06-27", "2026-07-04", "2026-10-31"} {
+ got := temporalEF(d(day))
+ if got.Cel.Colour != White {
+ t.Errorf("%s: colour = %s, want white (RG 78, Our Lady on Saturday)", day, got.Cel.Colour)
+ }
+ if got.Cel.Rank != RankClass4 {
+ t.Errorf("%s: rank = %v, want class-4 -- the office does not change the rank", day, got.Cel.Rank)
+ }
+ if !strings.HasPrefix(got.Cel.Slug, "ef-time-after-pentecost-") {
+ t.Errorf("%s: slug = %q, want the ferial slug unchanged -- the readings are "+
+ "still the feria's and a bespoke slug would recur many times a year", day, got.Cel.Slug)
+ }
+ }
+ // Saturdays whose feria is NOT IV class keep their own colour. Lent and
+ // Advent ferias are III class and violet; a fix that whitened every
+ // Saturday would fail here.
+ for _, c := range []struct {
+ day string
+ colour Colour
+ }{
+ {"2026-03-07", Violet}, // Saturday in Lent
+ {"2026-12-05", Violet}, // Saturday in Advent
+ {"2026-04-04", Violet}, // Holy Saturday -- I class, privileged
+ } {
+ if got := temporalEF(d(c.day)).Cel.Colour; got != c.colour {
+ t.Errorf("%s: colour = %s, want %s -- RG 78 applies only where the feria is IV class",
+ c.day, got, c.colour)
+ }
+ }
+}