mirror of
https://git.pumpin.online/funkpower/typikon.git
synced 2026-10-23 03:07:12 +00:00
143 lines
4.6 KiB
Rust
143 lines
4.6 KiB
Rust
//! Pascha, and the movable cycle that hangs off it.
|
|||
|
|
//!
|
||
|
|
//! Two reckonings are in use. The **Julian Paschalion** is what nearly every
|
||
|
|
//! Orthodox Church keeps: the old computus, worked in the Julian calendar and
|
||
|
|
//! then read off onto a civil date. The **Gregorian Paschalion** is the Western
|
||
|
|
//! one, kept by the Finnish Orthodox Church and by most Byzantine Catholics.
|
||
|
|
//!
|
||
|
|
//! Neither is a variant of the other. They are separate tables that happen to
|
||
|
|
//! agree in some years, 2025 falls on 20 April by both, and can diverge by as
|
||
|
|
//! much as five weeks.
|
||
|
|
|
||
|
|
use crate::calendars::{Date, JulianDate};
|
||
|
|
|
||
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||
|
|
pub enum Paschalion {
|
||
|
|
Julian,
|
||
|
|
Gregorian,
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Pascha by the Julian Paschalion, as a civil (Gregorian) date.
|
||
|
|
///
|
||
|
|
/// Meeus' Julian algorithm yields a date in the *Julian* calendar, which is
|
||
|
|
/// then read onto the civil one. The type system enforces that step here: the
|
||
|
|
/// algorithm builds a `JulianDate`, and only `to_civil` produces a `Date`.
|
||
|
|
pub fn julian_pascha(year: i32) -> Date {
|
||
|
|
let a = year % 4;
|
||
|
|
let b = year % 7;
|
||
|
|
let c = year % 19;
|
||
|
|
let d = (19 * c + 15) % 30;
|
||
|
|
let e = (2 * a + 4 * b - d + 34) % 7;
|
||
|
|
let month = ((d + e + 114) / 31) as u32;
|
||
|
|
let day = (((d + e + 114) % 31) + 1) as u32;
|
||
|
|
JulianDate { year, month, day }.to_civil()
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Pascha by the Gregorian Paschalion, the Western computus.
|
||
|
|
pub fn gregorian_pascha(year: i32) -> Date {
|
||
|
|
let a = year % 19;
|
||
|
|
let b = year / 100;
|
||
|
|
let c = year % 100;
|
||
|
|
let d = b / 4;
|
||
|
|
let e = b % 4;
|
||
|
|
let g = (8 * b + 13) / 25;
|
||
|
|
let h = (19 * a + b - d - g + 15) % 30;
|
||
|
|
let i = c / 4;
|
||
|
|
let k = c % 4;
|
||
|
|
let l = (32 + 2 * e + 2 * i - h - k) % 7;
|
||
|
|
let m = (a + 11 * h + 19 * l) / 433;
|
||
|
|
let month = ((h + l - 7 * m + 90) / 25) as u32;
|
||
|
|
let day = ((h + l - 7 * m + 33 * month as i32 + 19) % 32) as u32;
|
||
|
|
Date::from_ymd(year, month, day).expect("computus yields a real date")
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn pascha(year: i32, p: Paschalion) -> Date {
|
||
|
|
match p {
|
||
|
|
Paschalion::Julian => julian_pascha(year),
|
||
|
|
Paschalion::Gregorian => gregorian_pascha(year),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Every movable date the calendar needs, keyed off Pascha.
|
||
|
|
///
|
||
|
|
/// All of these are counted in real days from Pascha, so they are civil dates
|
||
|
|
/// already and need no calendar conversion: the distance from Pascha to
|
||
|
|
/// Pentecost is fifty days in every reckoning.
|
||
|
|
///
|
||
|
|
/// A struct rather than a map, so a typo in a key is a compile error instead
|
||
|
|
/// of a silent `None` at the far end of the program.
|
||
|
|
#[derive(Clone, Copy, Debug)]
|
||
|
|
pub struct Movables {
|
||
|
|
pub pascha: Date,
|
||
|
|
|
||
|
|
// the Triodion, counted backwards
|
||
|
|
pub publican_pharisee: Date,
|
||
|
|
pub prodigal_son: Date,
|
||
|
|
pub meatfare: Date,
|
||
|
|
pub cheesefare: Date,
|
||
|
|
pub cheesefare_week_start: Date,
|
||
|
|
pub clean_monday: Date,
|
||
|
|
pub orthodoxy_sunday: Date,
|
||
|
|
pub gregory_palamas: Date,
|
||
|
|
pub cross_veneration: Date,
|
||
|
|
pub john_climacus: Date,
|
||
|
|
pub mary_of_egypt: Date,
|
||
|
|
/// The Forty Days end here, on the Friday before Lazarus Saturday.
|
||
|
|
pub great_fast_end: Date,
|
||
|
|
pub lazarus_saturday: Date,
|
||
|
|
pub palm_sunday: Date,
|
||
|
|
pub great_week_start: Date,
|
||
|
|
pub great_thursday: Date,
|
||
|
|
pub great_friday: Date,
|
||
|
|
pub holy_saturday: Date,
|
||
|
|
|
||
|
|
// the Pentecostarion, counted forwards
|
||
|
|
pub bright_week_end: Date,
|
||
|
|
pub thomas_sunday: Date,
|
||
|
|
pub myrrhbearers: Date,
|
||
|
|
pub midfeast: Date,
|
||
|
|
pub ascension: Date,
|
||
|
|
pub fathers_first_council: Date,
|
||
|
|
pub pentecost: Date,
|
||
|
|
pub pentecost_week_end: Date,
|
||
|
|
pub all_saints: Date,
|
||
|
|
/// The Apostles' Fast begins the Monday after All Saints. Its end is a
|
||
|
|
/// fixed ecclesiastical date, so the jurisdiction resolves that.
|
||
|
|
pub apostles_start: Date,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn movable_cycle(year: i32, p: Paschalion) -> Movables {
|
||
|
|
let d = pascha(year, p);
|
||
|
|
Movables {
|
||
|
|
pascha: d,
|
||
|
|
publican_pharisee: d - 70,
|
||
|
|
prodigal_son: d - 63,
|
||
|
|
meatfare: d - 56,
|
||
|
|
cheesefare_week_start: d - 55,
|
||
|
|
cheesefare: d - 49,
|
||
|
|
clean_monday: d - 48,
|
||
|
|
orthodoxy_sunday: d - 42,
|
||
|
|
gregory_palamas: d - 35,
|
||
|
|
cross_veneration: d - 28,
|
||
|
|
john_climacus: d - 21,
|
||
|
|
mary_of_egypt: d - 14,
|
||
|
|
great_fast_end: d - 9,
|
||
|
|
lazarus_saturday: d - 8,
|
||
|
|
palm_sunday: d - 7,
|
||
|
|
great_week_start: d - 6,
|
||
|
|
great_thursday: d - 3,
|
||
|
|
great_friday: d - 2,
|
||
|
|
holy_saturday: d - 1,
|
||
|
|
bright_week_end: d + 6,
|
||
|
|
thomas_sunday: d + 7,
|
||
|
|
myrrhbearers: d + 14,
|
||
|
|
midfeast: d + 24,
|
||
|
|
ascension: d + 39,
|
||
|
|
fathers_first_council: d + 42,
|
||
|
|
pentecost: d + 49,
|
||
|
|
pentecost_week_end: d + 55,
|
||
|
|
all_saints: d + 56,
|
||
|
|
apostles_start: d + 57,
|
||
|
|
}
|
||
|
|
}
|