時間/時刻 - 暦 - ツェラーの公式
参考
例題
/// Calendar - Zeller's Theorem
#[derive(Debug, PartialEq, Eq)]
pub enum Day {
Sat,
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
}
#[derive(Debug, PartialEq, Eq)]
pub enum CalendarType {
Julian, // when 4 <= y && y <= 1582
Gregorian, // when 1582 <= y
}
impl Day {
fn from(i: usize) -> Day {
match i {
0 => Day::Sat,
1 => Day::Sun,
2 => Day::Mon,
3 => Day::Tue,
4 => Day::Wed,
5 => Day::Thu,
6 => Day::Fri,
_ => panic!("no day"),
}
}
}
impl std::fmt::Display for Day {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Day::Sat => "Saturday",
Day::Sun => "Sunday",
Day::Mon => "Monday",
Day::Tue => "Tuesday",
Day::Wed => "Wednesday",
Day::Thu => "Thursday",
Day::Fri => "Friday",
}
)
}
}
pub fn zeller(y: usize, m: usize, d: usize, ctype: CalendarType) -> Day {
assert!(m >= 1 && d >= 1);
let (year, month) = if m <= 2 { (y - 1, m + 12) } else { (y, m) };
let y_up = year % 100;
let y_down = year / 100;
let gamma = match ctype {
CalendarType::Gregorian => 5 * y_down + y_down / 4,
CalendarType::Julian => 6 * y_down + 5,
};
let h = d + (26 * (month + 1) / 10) + y_up + y_up / 4 + gamma;
Day::from(h % 7)
}
#[cfg(test)]
mod test_zeller {
#[test]
fn it_works() {
use crate::datetime::zeller::*;
assert_eq!(zeller(2020, 9, 13, CalendarType::Gregorian), Day::Sun);
assert_eq!(zeller(2019, 12, 25, CalendarType::Gregorian), Day::Wed);
assert_eq!(zeller(2018, 12, 25, CalendarType::Gregorian), Day::Tue);
assert_eq!(zeller(2010, 12, 25, CalendarType::Gregorian), Day::Sat);
assert_eq!(zeller(2001, 12, 25, CalendarType::Gregorian), Day::Tue);
}
}