badi_date/bahai_holy_day/
holy_day_providing.rs

1use crate::{BadiDateError, BadiDateLike, BahaiHolyDay};
2
3/// Provides methods to get the current, previous, and next Bahá’í holy day
4pub trait HolyDayProviding: BadiDateLike {
5    /// Gets the holy day for `self.day` if it is a holy day
6    fn holy_day(&self) -> Option<BahaiHolyDay> {
7        BahaiHolyDay::holy_days_for_year(self.year())
8            .get(&self.day_of_year())
9            .cloned()
10    }
11
12    /// Gets the next holy day, if within the supported date range
13    fn next_holy_day(&self) -> Result<Self, BadiDateError> {
14        for year in [self.year(), self.year() + 1] {
15            let after_day = if year == self.year() {
16                self.day_of_year()
17            } else {
18                0
19            };
20            if let Some((day_of_year, _holy_day)) = BahaiHolyDay::holy_days_for_year(year)
21                .into_iter()
22                .find(|(day_of_year, _)| *day_of_year > after_day)
23            {
24                return self.with_year_and_doy(year, day_of_year);
25            }
26        }
27        Err(BadiDateError::DateNotSupported)
28    }
29
30    /// Gets the previous holy day, if within the supported date range
31    fn previous_holy_day(&self) -> Result<Self, BadiDateError> {
32        for year in [self.year(), self.year() - 1] {
33            let before_day = if year == self.year() {
34                self.day_of_year()
35            } else {
36                366
37            };
38            if let Some((day_of_year, _holy_day)) = BahaiHolyDay::holy_days_for_year(year)
39                .into_iter()
40                .filter(|(day_of_year, _)| *day_of_year < before_day)
41                .last()
42            {
43                return self.with_year_and_doy(year, day_of_year);
44            }
45        }
46        Err(BadiDateError::DateNotSupported)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::{BadiDate, BadiDateOps, BadiMonth, BahaiHolyDay, HolyDayProviding};
53
54    #[test]
55    fn add_subtract_next_previous() {
56        // 2 Nur 181 B.E. / 5 June 2024
57        let badi = BadiDate::new(181, BadiMonth::Month(5), 2).unwrap();
58        let next_holy_day: BadiDate = badi.next_holy_day().unwrap();
59        assert_eq!(
60            next_holy_day,
61            // Martyrdom of the Báb
62            BadiDate::new(181, BadiMonth::Month(6), 17).unwrap(),
63        );
64        assert_eq!(
65            next_holy_day.holy_day(),
66            Some(BahaiHolyDay::MartyrdomOfTheBab)
67        );
68        assert!(next_holy_day.holy_day().unwrap().work_suspended());
69        let next_holy_day: BadiDate = next_holy_day.next_holy_day().unwrap();
70        assert_eq!(
71            next_holy_day,
72            // Birth of the Báb
73            BadiDate::new(181, BadiMonth::Month(12), 19).unwrap(),
74        );
75        assert_eq!(next_holy_day.holy_day(), Some(BahaiHolyDay::BirthOfTheBab));
76        let next_holy_day: BadiDate = next_holy_day.next_holy_day().unwrap();
77        assert_eq!(
78            next_holy_day,
79            // Birth of Bahá’u’lláh
80            BadiDate::new(181, BadiMonth::Month(13), 1).unwrap(),
81        );
82        assert_eq!(
83            next_holy_day.holy_day(),
84            Some(BahaiHolyDay::BirthOfBahaullah)
85        );
86        let next_day = next_holy_day.next_day();
87        assert_eq!(next_day.holy_day(), None);
88        let next_holy_day: BadiDate = next_holy_day
89            .next_holy_day()
90            .unwrap()
91            .next_holy_day()
92            .unwrap();
93        assert_eq!(
94            next_holy_day,
95            // Ascension of ‘Abdu’l-Bahá
96            BadiDate::new(181, BadiMonth::Month(14), 6).unwrap(),
97        );
98        let prev_holy_day = badi.previous_holy_day().unwrap();
99        assert_eq!(
100            prev_holy_day,
101            // Ascension of Bahá’u’lláh
102            BadiDate::new(181, BadiMonth::Month(4), 13).unwrap(),
103        );
104        let prev_holy_day = prev_holy_day.previous_holy_day().unwrap();
105        assert_eq!(
106            prev_holy_day,
107            // Declaration of the Báb
108            BadiDate::new(181, BadiMonth::Month(4), 8).unwrap(),
109        );
110
111        let badi = BadiDate::new(181, BadiMonth::AyyamIHa, 2).unwrap();
112        let next_holy_day: BadiDate = badi.next_holy_day().unwrap();
113        assert_eq!(
114            next_holy_day,
115            // Naw-Rúz
116            BadiDate::new(182, BadiMonth::Month(1), 1).unwrap(),
117        );
118        assert_eq!(next_holy_day.holy_day(), Some(BahaiHolyDay::NawRuz),);
119
120        let previous_holy_day: BadiDate = next_holy_day.previous_holy_day().unwrap();
121        assert_eq!(
122            previous_holy_day,
123            // Ascension of ‘Abdu’l-Bahá
124            BadiDate::new(181, BadiMonth::Month(14), 6).unwrap(),
125        );
126        assert_eq!(
127            previous_holy_day.holy_day(),
128            Some(BahaiHolyDay::AscensionOfAbdulBaha),
129        );
130        assert!(!previous_holy_day.holy_day().unwrap().work_suspended(),);
131    }
132}