From b01c0bc4825efa1b9633b2ad1679ef3d4badb55f Mon Sep 17 00:00:00 2001 From: Alex Lev Date: Tue, 16 Dec 2025 11:48:37 +0100 Subject: [PATCH] feat: add switzerland calendar --- crates/RustQuant_time/src/calendar.rs | 3 + crates/RustQuant_time/src/countries/mod.rs | 4 + .../src/countries/switzerland.rs | 152 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 crates/RustQuant_time/src/countries/switzerland.rs diff --git a/crates/RustQuant_time/src/calendar.rs b/crates/RustQuant_time/src/calendar.rs index ce3fffcb..3cbc435d 100644 --- a/crates/RustQuant_time/src/calendar.rs +++ b/crates/RustQuant_time/src/calendar.rs @@ -85,6 +85,8 @@ pub enum Market { UnitedKingdom, /// United States national calendar. UnitedStates, + /// Switzerland national calendar. + Switzerland, // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MARKETS / EXCHANGES // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -432,6 +434,7 @@ impl Calendar { Market::Singapore => is_holiday_impl_singapore(date), Market::UnitedKingdom => is_holiday_impl_united_kingdom(date), Market::UnitedStates => is_holiday_impl_united_states(date), + Market::Switzerland => is_holiday_impl_switzerland(date), // Special case markets: Market::None => false, Market::Weekends => false, diff --git a/crates/RustQuant_time/src/countries/mod.rs b/crates/RustQuant_time/src/countries/mod.rs index a44532b3..b5ed2fc1 100644 --- a/crates/RustQuant_time/src/countries/mod.rs +++ b/crates/RustQuant_time/src/countries/mod.rs @@ -112,3 +112,7 @@ pub(crate) use united_kingdom::*; /// United States holidays and calendars. pub mod united_states; pub(crate) use united_states::*; + +/// Switzerland holidays and calendars. +pub mod switzerland; +pub(crate) use switzerland::*; diff --git a/crates/RustQuant_time/src/countries/switzerland.rs b/crates/RustQuant_time/src/countries/switzerland.rs new file mode 100644 index 00000000..1e360238 --- /dev/null +++ b/crates/RustQuant_time/src/countries/switzerland.rs @@ -0,0 +1,152 @@ +use crate::utilities::unpack_date; +use time::{Date, Month}; + +pub(crate) fn is_holiday_impl_switzerland(date: Date) -> bool { + let (_, m, d, _, yd, em) = unpack_date(date, false); + + is_new_year(m, d) + || is_berchtholdstag(m, d) + || is_good_friday(yd, em) + || is_easter_monday(yd, em) + || is_labour_day(m, d) + || is_ascension_day(yd, em) + || is_whit_monday(yd, em) + || is_national_holiday(m, d) + || is_christmas_eve(m, d) + || is_christmas_day(m, d) + || is_st_stephens_day(m, d) + || is_new_year_eve(m, d) +} + +#[inline] +fn is_new_year(month: Month, day: u8) -> bool { + month == Month::January && day == 1 +} + +#[inline] +fn is_berchtholdstag(month: Month, day: u8) -> bool { + month == Month::January && day == 2 +} + +#[inline] +fn is_good_friday(yd: u16, em: u16) -> bool { + yd == em - 3 +} + +#[inline] +fn is_easter_monday(yd: u16, em: u16) -> bool { + yd == em +} + +#[inline] +fn is_labour_day(month: Month, day: u8) -> bool { + month == Month::May && day == 1 +} + +#[inline] +fn is_ascension_day(yd: u16, em: u16) -> bool { + yd == em + 38 +} + +#[inline] +fn is_whit_monday(yd: u16, em: u16) -> bool { + yd == em + 49 +} + +#[inline] +fn is_national_holiday(month: Month, day: u8) -> bool { + month == Month::August && day == 1 +} + +#[inline] +fn is_christmas_eve(month: Month, day: u8) -> bool { + month == Month::December && day == 24 +} + +#[inline] +fn is_christmas_day(month: Month, day: u8) -> bool { + month == Month::December && day == 25 +} + +#[inline] +fn is_st_stephens_day(month: Month, day: u8) -> bool { + month == Month::December && day == 26 +} + +#[inline] +fn is_new_year_eve(month: Month, day: u8) -> bool { + month == Month::December && day == 31 +} + +#[cfg(test)] +mod tests_switzerland { + use crate::{Calendar, Market}; + + const CALENDAR: Calendar = Calendar::new(Market::Switzerland); + + #[test] + fn new_years_day_2025() { + let date = time::macros::date!(2025 - 01 - 01); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn whit_monday_2025() { + let date = time::macros::date!(2025 - 06 - 09); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn regular_day_2025() { + let date = time::macros::date!(2025 - 03 - 17); + assert!(CALENDAR.is_business_day(date)); + } + + #[test] + fn national_holiday_2025() { + let date = time::macros::date!(2025 - 08 - 01); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn good_friday_2025() { + let date = time::macros::date!(2025 - 04 - 18); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn berchtholdstag_2025() { + let date = time::macros::date!(2025 - 01 - 02); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn ascension_2025() { + let date = time::macros::date!(2025 - 05 - 29); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn christmas_2025() { + let date = time::macros::date!(2025 - 12 - 25); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn st_stephens_day_2025() { + let date = time::macros::date!(2025 - 12 - 26); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn new_years_eve_2025() { + let date = time::macros::date!(2025 - 12 - 31); + assert!(!CALENDAR.is_business_day(date)); + } + + #[test] + fn christmas_eve_2025() { + let date = time::macros::date!(2025 - 12 - 24); + assert!(!CALENDAR.is_business_day(date)); + } +}