use crate::shared::shared;
use crate::time::calendar::{Calendar, CalendarImpl, is_weekend_sat_sun, western_easter_monday};
use crate::time::date::{Date, Month};
use crate::time::weekday::Weekday;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Market {
Sse,
}
pub struct Chile;
impl Chile {
pub fn new(market: Market) -> Calendar {
let imp: crate::shared::Shared<dyn CalendarImpl> = match market {
Market::Sse => shared(SseImpl),
};
Calendar::from_impl(imp)
}
}
fn is_aboriginal_people_day(d: i32, m: Month, y: i32) -> bool {
const ABORIGINAL_PEOPLE_DAY: [u8; 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, ];
if m != Month::June || y < 2021 {
return false;
}
let idx = (y - 2021) as usize;
idx < ABORIGINAL_PEOPLE_DAY.len() && d == ABORIGINAL_PEOPLE_DAY[idx] as i32
}
struct SseImpl;
impl CalendarImpl for SseImpl {
fn name(&self) -> String {
"Santiago Stock Exchange".to_string()
}
fn is_weekend(&self, w: Weekday) -> bool {
is_weekend_sat_sun(w)
}
fn is_business_day(&self, date: Date) -> bool {
let w = date.weekday();
let d = date.day_of_month();
let m = date.month();
let y = date.year();
let dd = date.day_of_year();
let em = western_easter_monday(y);
!(is_weekend_sat_sun(w)
|| (d == 1 && m == Month::January)
|| (d == 2 && m == Month::January && w == Weekday::Monday && y > 2016)
|| (d == 16 && m == Month::January && y == 2018)
|| (dd == em - 3)
|| (dd == em - 2)
|| (d == 19 && m == Month::April && y == 2017)
|| (d == 1 && m == Month::May)
|| (d == 21 && m == Month::May)
|| is_aboriginal_people_day(d, m, y)
|| (d >= 26 && d <= 29 && m == Month::June && w == Weekday::Monday)
|| (d == 2 && m == Month::July && w == Weekday::Monday)
|| (d == 16 && m == Month::July)
|| (d == 15 && m == Month::August)
|| (d == 16 && m == Month::September && y == 2022)
|| (d == 17
&& m == Month::September
&& ((w == Weekday::Monday && y >= 2007) || (w == Weekday::Friday && y > 2016)))
|| (d == 18 && m == Month::September)
|| (d == 19 && m == Month::September)
|| (d == 20 && m == Month::September && w == Weekday::Friday && y >= 2007)
|| (d >= 9 && d <= 12 && m == Month::October && w == Weekday::Monday)
|| (d == 15 && m == Month::October && w == Weekday::Monday)
|| (((d == 27 && m == Month::October && w == Weekday::Friday)
|| (d == 31
&& m == Month::October
&& w != Weekday::Tuesday
&& w != Weekday::Wednesday)
|| (d == 2 && m == Month::November && w == Weekday::Friday))
&& y >= 2008)
|| (d == 1 && m == Month::November)
|| (d == 8 && m == Month::December)
|| (d == 25 && m == Month::December)
|| (d == 31 && m == Month::December))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn name_matches_quantlib() {
assert_eq!(Chile::new(Market::Sse).name(), "Santiago Stock Exchange");
}
#[test]
fn fixed_holidays() {
let c = Chile::new(Market::Sse);
assert!(c.is_holiday(Date::new(1, Month::January, 2019))); assert!(c.is_holiday(Date::new(1, Month::May, 2019))); assert!(c.is_holiday(Date::new(21, Month::May, 2019))); assert!(c.is_holiday(Date::new(16, Month::July, 2019))); assert!(c.is_holiday(Date::new(15, Month::August, 2019))); assert!(c.is_holiday(Date::new(18, Month::September, 2019))); assert!(c.is_holiday(Date::new(19, Month::September, 2019))); assert!(c.is_holiday(Date::new(1, Month::November, 2019))); assert!(c.is_holiday(Date::new(8, Month::December, 2019))); assert!(c.is_holiday(Date::new(25, Month::December, 2019))); assert!(c.is_holiday(Date::new(31, Month::December, 2019))); }
#[test]
fn weekend_rule() {
let c = Chile::new(Market::Sse);
assert!(c.is_weekend(Weekday::Saturday));
assert!(c.is_weekend(Weekday::Sunday));
}
}