use crate::time::calendars::Calendar;
use chrono::{NaiveDate, Weekday};
use serde::{Deserialize, Serialize};
static ABORIGINAL_PEOPLE_DAY: [u32; 179] = [
21, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 21, 20, 20, 20, 20, ];
#[derive(Deserialize, Serialize, Default, Debug)]
pub struct Chile;
impl Chile {
fn is_aboriginal_people_day(&self, date: NaiveDate) -> bool {
let (d, _, m, y, _) = self.naive_date_to_dkmy(date);
m == 6 && y >= 2021 && d == ABORIGINAL_PEOPLE_DAY[y as usize - 2021usize]
}
}
#[typetag::serde]
impl Calendar for Chile {
fn is_business_day(&self, date: NaiveDate) -> bool {
let (d, w, m, y, dd) = self.naive_date_to_dkmy(date);
let em = self.easter_monday(y);
if self.is_weekend(date)
|| (d == 1 && m == 1)
|| (d == 2 && m == 1 && w == Weekday::Mon && y > 2016)
|| (d == 16 && m == 1 && y == 2018)
|| (dd == em - 3)
|| (dd == em - 2)
|| (d == 19 && m == 4 && y == 2017)
|| (d == 1 && m == 5)
|| (d == 21 && m == 5)
|| self.is_aboriginal_people_day(date)
|| ((26..=29).contains(&d) && m == 6 && w == Weekday::Mon)
|| (d == 2 && m == 7 && w == Weekday::Mon)
|| (d == 16 && m == 7)
|| (d == 15 && m == 8)
|| (d == 16 && m == 9 && y == 2022)
|| (d == 17 && m == 9 && ((w == Weekday::Mon && y >= 2007) || (w == Weekday::Fri && y > 2016)))
|| (d == 18 && m == 9)
|| (d == 19 && m == 9)
|| (d == 20 && m == 9 && w == Weekday::Fri && y >= 2007)
|| ((9..=12).contains(&d) && m == 10 && w == Weekday::Mon)
|| (d == 15 && m == 10 && w == Weekday::Mon)
|| (((d == 27 && m == 10 && w == Weekday::Fri)
|| (d == 31 && m == 10 && w != Weekday::Tue && w != Weekday::Wed)
|| (d == 2 && m == 11 && w == Weekday::Fri)) && y >= 2008)
|| (d == 1 && m == 11)
|| (d == 8 && m == 12)
|| (d == 25 && m == 12)
|| (d ==31 && m == 12)
{
return false;
}
true
}
}
#[cfg(test)]
mod tests {
use super::Chile;
use crate::time::calendars::Calendar;
use chrono::{Duration, NaiveDate};
#[test]
fn test_chile_holiday() {
let expected_results_for_2023 = vec![
false, false, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true,
false, false, false, true, true, true, true, true, false, false, true, true, true,
true, true, false, false, true, true, true, true, true, false, false, false, true,
true, true, true, false, false, true, true, true, true, true, false, false, true, true,
true, true, true, false, false, true, true, true, true, true, false, false, true, true,
true, true, true, false, false, true, true, true, true, true, false, false, true, true,
true, true, true, false, false, true, true, false, true, true, false, false, false,
true, true, true, true, false, false, true, true, true, true, true, false, false, true,
true, true, true, true, false, false, true, true, true, true, true, false, false, true,
true, true, true, true, false, false, true, true, true, true, true, false, false, true,
true, true, true, true, false, false, true, false, true, true, true, false, false,
true, true, true, true, true, false, false, true, true, true, true, true, false, false,
true, true, true, true, true, false, false, true, true, true, true, true, false, false,
false, false, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, false, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true,
false, false, false, true, true, false, true, true, false, false, true, true, true,
true, true, false, false, true, true, true, true, true, false, false, true, true, true,
true, true, false, false, true, true, true, true, true, false, false, true, true, true,
true, false, false, false, true, true, true, true, true, false, false, true, true,
true, true, true, false, false, false, true, true, true, true, false, false,
];
let first_date = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap();
for n in 0i32..365 {
let target_date = first_date + Duration::try_days(n as i64).unwrap();
let expected = expected_results_for_2023[n as usize];
assert_eq!(Chile.is_business_day(target_date), expected);
}
let expected_results_for_2024 = vec![
false, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, false, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, false, true,
true, false, false, true, true, true, true, true, false, false, true, true, true, true,
true, false, false, true, false, true, true, true, false, false, true, true, true,
true, true, false, false, true, true, true, true, true, false, false, true, true, true,
true, true, false, false, true, true, true, false, true, false, false, true, true,
true, true, true, false, false, true, true, true, true, true, false, false, true, true,
true, true, true, false, false, true, false, true, true, true, false, false, true,
true, true, true, true, false, false, true, true, true, true, true, false, false, true,
true, true, true, true, false, false, true, true, true, false, true, false, false,
true, true, true, true, true, false, false, true, true, true, true, true, false, false,
true, true, true, true, true, false, false, true, true, true, true, true, false, false,
true, true, false, false, false, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, true, true, false, false, true, true, true, true, true, false,
false, true, true, true, false, false, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, true, true, true, false, false, true, true, true, true, true,
false, false, true, true, false, true, true, false, false, true, false,
];
let first_date = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
for n in 0i32..365 {
let target_date = first_date + Duration::try_days(n as i64).unwrap();
let expected = expected_results_for_2024[n as usize];
assert_eq!(Chile.is_business_day(target_date), expected);
}
}
}