extern crate chrono;
use chrono::Datelike;
const APOSTLES: [&str; 5] = ["Mungday", "Mojoday", "Syaday", "Zaraday", "Maladay"];
const HOLYDAYS: [&str; 5] = ["Chaoflux", "Discoflux", "Confuflux", "Bureflux", "Afflux"];
const SEASONS: [&str; 5] = [
"Chaos",
"Discord",
"Confusion",
"Bureaucracy",
"The Aftermath",
];
const WEEKDAYS: [&str; 5] = [
"Sweetmorn",
"Boomtime",
"Pungenday",
"Prickle-Prickle",
"Setting Orange",
];
const APOSTLE_HOLYDAY: usize = 5;
const ST_TIBS_DAY: usize = 59;
const SEASON_DAYS: usize = 73;
const SEASON_HOLYDAY: usize = 50;
const WEEK_DAYS: usize = 5;
const CURSE_OF_GREYFACE: i32 = 1166;
pub trait DiscordianDate: Datelike {
fn to_poee(&self) -> String {
let day = self.ordinal0() as usize;
let leap = self.year() % 4 == 0 && self.year() % 100 != 0 || self.year() % 400 == 0;
let year = self.year() + CURSE_OF_GREYFACE;
if leap && day == ST_TIBS_DAY {
return format!("St. Tib's Day, in the YOLD {}", year);
}
let day_offset = if leap && day > ST_TIBS_DAY {
day - 1
} else {
day
};
let day_of_season = day_offset % SEASON_DAYS + 1;
let season = SEASONS[day_offset / SEASON_DAYS];
let weekday = WEEKDAYS[day_offset % WEEK_DAYS];
let holiday = if day_of_season == APOSTLE_HOLYDAY {
format!("\nCelebrate {}", APOSTLES[day_offset / SEASON_DAYS])
} else if day_of_season == SEASON_HOLYDAY {
format!("\nCelebrate {}", HOLYDAYS[day_offset / SEASON_DAYS])
} else {
String::with_capacity(0)
};
format!(
"{}, the {} day of {} in the YOLD {}{}",
weekday,
ordinalize(day_of_season),
season,
year,
holiday
)
}
}
impl<T: Datelike> DiscordianDate for T {}
fn ordinalize(num: usize) -> String {
let s = format!("{}", num);
let suffix = if s.ends_with('1') && !s.ends_with("11") {
"st"
} else if s.ends_with('2') && !s.ends_with("12") {
"nd"
} else if s.ends_with('3') && !s.ends_with("13") {
"rd"
} else {
"th"
};
format!("{}{}", s, suffix)
}
#[cfg(test)]
mod tests {
use super::DiscordianDate;
use chrono::{TimeZone, Utc};
#[test]
fn day_one_test() {
assert_eq!(
"Sweetmorn, the 1st day of Chaos in the YOLD 0",
Utc.ymd(-1166, 1, 1).to_poee()
);
}
#[test]
fn ante_tibs_test() {
assert_eq!(
"Prickle-Prickle, the 59th day of Chaos in the YOLD 3166",
Utc.ymd(2000, 2, 28).to_poee()
);
}
#[test]
fn tibs_test() {
assert_eq!(
"St. Tib's Day, in the YOLD 3166",
Utc.ymd(2000, 2, 29).to_poee()
);
}
#[test]
fn post_tibs_test() {
assert_eq!(
"Setting Orange, the 60th day of Chaos in the YOLD 3166",
Utc.ymd(2000, 3, 1).to_poee()
);
}
#[test]
fn ante_anti_tibs_test() {
assert_eq!(
"Prickle-Prickle, the 59th day of Chaos in the YOLD 2232",
Utc.ymd(1066, 2, 28).to_poee()
);
}
#[test]
fn post_anti_tibs_test() {
assert_eq!(
"Setting Orange, the 60th day of Chaos in the YOLD 2232",
Utc.ymd(1066, 3, 1).to_poee()
);
}
#[test]
fn holy_test() {
assert_eq!(
"Prickle-Prickle, the 50th day of Bureaucracy in the YOLD 3183\nCelebrate Bureflux",
Utc.ymd(2017, 9, 26).to_poee()
);
}
#[test]
fn apos_test() {
assert_eq!(
"Boomtime, the 5th day of The Aftermath in the YOLD 3183\nCelebrate Maladay",
Utc.ymd(2017, 10, 24).to_poee()
);
}
}