2026-09-18 11:13:10 -04:00
//! Who keeps which calendar, and by whose rule.
//!
//! A jurisdiction is four independent choices, and conflating any two of them
//! is how calendar code usually goes wrong:
//!
//! - **paschalion**: which table gives Pascha
//! - **menologion**: which calendar the fixed feasts are read on
//! - **rule**: which fasting discipline is kept
//! - **menaia**: which supplementary commemorations to load, if any
//!
//! The pairings are not free. Almost every Orthodox Church keeps the Julian
//! Paschalion; what divides them is the menologion. The "old calendar" churches
//! read the fixed feasts on the Julian calendar too, the "new calendar"
//! churches on the Revised Julian, which agrees with the Gregorian for every
//! date until 2800. So a new-calendar church keeps the Nativity with the West
//! and Pascha with the East, which is not a compromise but exactly what the
//! 1923 congress decided.
//!
//! Only two bodies here use the Gregorian Paschalion: the Finnish Orthodox
//! Church, alone among the Orthodox, and the Byzantine Catholic churches.
use crate ::calendars ::Date ;
use crate ::paschalion ::Paschalion ;
/// Which calendar the *fixed* feasts are read on.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum MenologionKind {
Julian ,
/// Revised Julian, which agrees with the Gregorian for every date until 2800.
RevisedJulian ,
}
2026-09-18 11:28:40 -04:00
/// Greek or Slavic usage. Both keep the same Typikon; they read it a little
/// differently, and the differences are small, real and printed in every
/// calendar that takes a side.
///
/// Two are modelled here:
///
/// - **The Protection of the Theotokos**, 1 October, is a great feast in
/// Slavic usage. Greek practice ranks it lower, and the Church of Greece
/// keeps it on 28 October besides.
/// - **Fish in the Nativity Fast.** Greek practice permits fish on any day but
/// Wednesday and Friday until 17 December; Slavic practice keeps fish to
/// Saturdays and Sundays throughout.
///
/// The split is coarse: a church is assigned the usage its books follow, and
/// no jurisdiction is wholly one thing. Override it with `--tradition`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Tradition {
Slavic ,
Greek ,
}
impl Tradition {
pub fn key ( self ) -> & 'static str {
match self {
Tradition ::Slavic => "slavic" ,
Tradition ::Greek => "greek" ,
}
}
pub fn parse ( s : & str ) -> Option < Tradition > {
match s . trim (). to_ascii_lowercase (). as_str () {
"slavic" | "russian" | "slav" => Some ( Tradition ::Slavic ),
"greek" | "byzantine" => Some ( Tradition ::Greek ),
_ => None ,
}
}
}
2026-09-18 11:13:10 -04:00
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum RuleKind {
Orthodox ,
Ruthenian ,
}
/// The short name people use for a paschalion/menologion combination.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Calendar {
Old ,
New ,
Western ,
}
impl Calendar {
pub fn key ( self ) -> & 'static str {
match self {
Calendar ::Old => "old" ,
Calendar ::New => "new" ,
Calendar ::Western => "western" ,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Jurisdiction {
pub key : & 'static str ,
pub name : & 'static str ,
pub paschalion : Paschalion ,
pub menologion : MenologionKind ,
2026-09-18 12:21:06 -04:00
/// Whose particular law decides what binds, and, unless `discipline`
/// says otherwise, at what level the day is shown.
2026-09-18 11:13:10 -04:00
pub rule : RuleKind ,
2026-09-18 12:21:06 -04:00
/// Show the day at another tradition's discipline while still reporting
/// this church's obligations.
///
/// The Eastern Catholic churches are the case this exists for. Their
/// tradition is the Byzantine fast entire; their law requires very much
/// less of it. Reporting only the law makes the Great Fast look like four
/// days of abstinence a year, which is what binds and not what is kept.
pub discipline : Option < RuleKind > ,
2026-09-18 11:28:40 -04:00
pub tradition : Tradition ,
2026-09-18 11:13:10 -04:00
/// Supplementary commemoration sets to overlay, fetched not shipped.
pub menaia : & 'static [ & 'static str ],
pub note : & 'static str ,
}
impl Jurisdiction {
pub fn calendar ( & self ) -> Calendar {
match ( self . paschalion , self . menologion ) {
( Paschalion ::Gregorian , MenologionKind ::RevisedJulian ) => Calendar ::Western ,
( _ , MenologionKind ::Julian ) => Calendar ::Old ,
_ => Calendar ::New ,
}
}
/// The ecclesiastical (year, month, day) a civil date is reckoned as.
pub fn fixed_of_civil ( & self , date : Date ) -> ( i32 , u32 , u32 ) {
match self . menologion {
MenologionKind ::Julian => {
let j = date . to_julian ();
( j . year , j . month , j . day )
}
MenologionKind ::RevisedJulian => date . ymd (),
}
}
/// The civil date of an ecclesiastical date in a given church year.
pub fn civil_of_fixed ( & self , year : i32 , month : u32 , day : u32 ) -> Date {
match self . menologion {
MenologionKind ::Julian => {
crate ::calendars ::JulianDate { year , month , day }. to_civil ()
}
MenologionKind ::RevisedJulian => Date ::from_ymd ( year , month , day )
. unwrap_or_else ( || Date ::from_ymd ( year , month , 28 ). expect ( "28th exists" )),
}
}
}
use MenologionKind ::{ Julian as JulMen , RevisedJulian as RevJul };
use Paschalion ::{ Gregorian as GregP , Julian as JulP };
use RuleKind ::{ Orthodox as Orth , Ruthenian as Ruth };
2026-09-18 11:28:40 -04:00
use Tradition ::{ Greek as Gk , Slavic as Sl };
2026-09-18 11:13:10 -04:00
const NO_MENAIA : & [ & str ] = & [];
const RUTHENIAN_MENAIA : & [ & str ] = & [ "ruthenian" ];
/// A reckoning without naming a church. `new` is the default.
pub const CALENDARS : & [ Jurisdiction ] = & [
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "old" , name : "Old Calendar" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Julian throughout, the reckoning of Moscow, Serbia, Georgia, Jerusalem and the Holy Mountain." },
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "new" , name : "New Calendar" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Revised Julian fixed feasts with the Julian Paschalion: Constantinople, Greece, Antioch, Romania, Bulgaria, the OCA." },
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "western" , name : "Gregorian" , paschalion : GregP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Gregorian throughout, Pascha included. Kept by the Finnish Orthodox Church and by most Byzantine Catholics." },
];
pub const JURISDICTIONS : & [ Jurisdiction ] = & [
// old calendar
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "moscow" , name : "Russian Orthodox Church" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "rocor" , name : "Russian Orthodox Church Outside Russia" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "serbian" , name : "Serbian Orthodox Church" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "georgian" , name : "Georgian Orthodox Church" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "jerusalem" , name : "Patriarchate of Jerusalem" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "athos" , name : "The Holy Mountain" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Athonite practice is stricter than the printed Typikon at many points." },
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "polish" , name : "Polish Orthodox Church" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Returned to the Julian menologion in 2014 after decades on the Revised Julian; some parishes kept the new calendar." },
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "macedonian" , name : "Macedonian Orthodox Church" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "acrod" , name : "American Carpatho-Russian Orthodox Diocese" , paschalion : JulP , menologion : JulMen , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA ,
2026-09-18 12:15:05 -04:00
note : "The Carpatho-Rusyn diocese under Constantinople, formed from the Greek Catholic parishes that returned to Orthodoxy in 1938. The diocese publishes both an old-calendar and a new-calendar cycle and its parishes keep one or the other; this entry is the old one, and `--calendar new --tradition slavic` is the other." },
2026-09-18 11:13:10 -04:00
// new calendar
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "constantinople" , name : "Ecumenical Patriarchate" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "goarch" , name : "Greek Orthodox Archdiocese of America" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "greece" , name : "Church of Greece" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "antiochian" , name : "Antiochian Orthodox Church" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "oca" , name : "Orthodox Church in America" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Most parishes keep the new calendar; a minority, chiefly of Carpatho-Russian and Alaskan background, keep the old." },
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "romanian" , name : "Romanian Orthodox Church" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "bulgarian" , name : "Bulgarian Orthodox Church" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "cyprus" , name : "Church of Cyprus" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "albanian" , name : "Orthodox Church of Albania" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA , note : "" },
Jurisdiction { key : "ukrainian" , name : "Orthodox Church of Ukraine" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Sl , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Moved the fixed feasts to the Revised Julian calendar on 1 September 2023. The Julian Paschalion is retained." },
// gregorian throughout
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "finnish" , name : "Finnish Orthodox Church" , paschalion : GregP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "The only Orthodox Church keeping the Gregorian Paschalion." },
// eastern catholic
2026-09-18 12:21:06 -04:00
Jurisdiction { key : "ruthenian" , name : "Byzantine Catholic Metropolia of Pittsburgh" , paschalion : GregP , menologion : RevJul , rule : Ruth , discipline : None , tradition : Sl , menaia : RUTHENIAN_MENAIA ,
2026-09-18 11:13:10 -04:00
note : "Gregorian throughout. Fasting is reported under Ruthenian particular law, which binds far less than the Typikon prescribes." },
2026-09-18 13:03:13 -04:00
Jurisdiction { key : "ugcc" , name : "Ukrainian Greek Catholic Church" , paschalion : JulP , menologion : RevJul , rule : Orth , discipline : None , tradition : Sl , menaia : RUTHENIAN_MENAIA ,
note : "Moved the fixed feasts to the Revised Julian calendar on 1 September 2023, keeping the Julian Paschalion. Eparchies outside Ukraine vary; several keep the Gregorian Paschalion. Its particular law on fasting is its own and is not modelled here, so the days are shown at the Typikon and nothing is reported as binding." },
Jurisdiction { key : "melkite" , name : "Melkite Greek Catholic Church" , paschalion : GregP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
note : "Practice is not uniform: parishes in the Middle East commonly keep the Julian Paschalion for the sake of the local Orthodox. Its particular law on fasting is its own and is not modelled here, so the days are shown at the Typikon and nothing is reported as binding." },
Jurisdiction { key : "romanian-catholic" , name : "Romanian Greek Catholic Church" , paschalion : GregP , menologion : RevJul , rule : Orth , discipline : None , tradition : Gk , menaia : NO_MENAIA ,
note : "Its particular law on fasting is its own and is not modelled here, so the days are shown at the Typikon and nothing is reported as binding." },
2026-09-18 11:13:10 -04:00
];
/// A jurisdiction key, a calendar name, or `None` for the default.
pub fn resolve ( name : Option <& str > ) -> Result <& 'static Jurisdiction , String > {
let Some ( name ) = name else {
return Ok ( & CALENDARS [ 1 ]); // new
};
let key = name . trim (). to_ascii_lowercase ();
JURISDICTIONS
. iter ()
. chain ( CALENDARS . iter ())
. find ( | j | j . key == key )
. ok_or_else ( || name . to_string ())
}