1use crate::time::calendars::Calendar;
4
5use chrono::NaiveDate;
6use serde::{Deserialize, Serialize};
7
8#[derive(Deserialize, Serialize, Debug)]
9pub enum ItalyMarket {
10 Settlement,
11 Exchange,
12}
13
14#[derive(Deserialize, Serialize, Default, Debug)]
15pub struct Italy {
16 pub market: Option<ItalyMarket>,
17}
18
19impl Italy {
20 fn settlement_is_business_day(&self, date: NaiveDate) -> bool {
21 let (d, _, m, y, dd) = self.naive_date_to_dkmy(date);
22 let em = self.easter_monday(y);
23
24 if self.is_weekend(date)
25 || (d == 1 && m == 1)
27 || (d == 6 && m == 1)
29 || (dd == em)
31 || (d == 25 && m == 4)
33 || (d == 1 && m == 5)
35 || (d == 2 && m == 6 && y >= 2000)
37 || (d == 15 && m == 8)
39 || (d == 1 && m == 11)
41 || (d == 8 && m == 12)
43 || (d == 25 && m == 12)
45 || (d == 26 && m == 12)
47 || (d == 31 && m == 12 && y == 1999)
49 {
50 return false;
51 }
52 true
53 }
54
55 fn exchange_is_business_day(&self, date: NaiveDate) -> bool {
56 let (d, _, m, y, dd) = self.naive_date_to_dkmy(date);
57 let em = self.easter_monday(y);
58 if self.is_weekend(date)
59 || (d == 1 && m == 1)
61 || (dd == em-3)
63 || (dd == em)
65 || (d == 1 && m == 5)
67 || (d == 15 && m == 8)
69 || (d == 24 && m == 12)
71 || (d == 25 && m == 12)
73 || (d == 26 && m == 12)
75 || (d == 31 && m == 12)
77 {
78 return false;
79 }
80 true
81 }
82}
83
84#[typetag::serde]
85impl Calendar for Italy {
86 fn is_business_day(&self, date: NaiveDate) -> bool {
87 match self.market {
88 Some(ItalyMarket::Settlement) => self.settlement_is_business_day(date),
89 Some(ItalyMarket::Exchange) => self.exchange_is_business_day(date),
90 None => self.settlement_is_business_day(date),
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::Italy;
98 use crate::time::calendars::Calendar;
99 use chrono::{Duration, NaiveDate};
100
101 #[test]
102 fn test_italy_holiday() {
103 let expected_results_for_2023 = vec![
105 false, true, true, true, true, false, false, false, true, true, true, true, true,
106 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
107 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
108 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
109 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
110 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
111 false, false, true, true, true, true, true, false, false, true, true, true, true, true,
112 false, false, false, true, true, true, true, false, false, true, true, true, true,
113 true, false, false, true, false, true, true, true, false, false, false, true, true,
114 true, true, false, false, true, true, true, true, true, false, false, true, true, true,
115 true, true, false, false, true, true, true, true, true, false, false, true, true, true,
116 true, false, false, false, true, true, true, true, true, false, false, true, true,
117 true, true, true, false, false, true, true, true, true, true, false, false, true, true,
118 true, true, true, false, false, true, true, true, true, true, false, false, true, true,
119 true, true, true, false, false, true, true, true, true, true, false, false, true, true,
120 true, true, true, false, false, true, true, true, true, true, false, false, true, true,
121 true, true, true, false, false, true, false, true, true, true, false, false, true,
122 true, true, true, true, false, false, true, true, true, true, true, false, false, true,
123 true, true, true, true, false, false, true, true, true, true, true, false, false, true,
124 true, true, true, true, false, false, true, true, true, true, true, false, false, true,
125 true, true, true, true, false, false, true, true, true, true, true, false, false, true,
126 true, true, true, true, false, false, true, true, true, true, true, false, false, true,
127 true, false, true, true, false, false, true, true, true, true, true, false, false,
128 true, true, true, true, true, false, false, true, true, true, true, true, false, false,
129 true, true, true, true, true, false, false, true, true, true, true, false, false,
130 false, true, true, true, true, true, false, false, true, true, true, true, true, false,
131 false, false, false, true, true, true, false, false,
132 ];
133 let first_date = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap();
134 for n in 0i32..365 {
135 let target_date = first_date + Duration::try_days(n as i64).unwrap();
136 let expected = expected_results_for_2023[n as usize];
137 assert_eq!(Italy::default().is_business_day(target_date), expected);
138 }
139 }
140}