rateslib/scheduling/calendars/
calendar.rs1use chrono::prelude::*;
2use pyo3::{FromPyObject, IntoPyObject};
3use serde::{Deserialize, Serialize};
4use std::convert::From;
5
6use crate::scheduling::{Cal, CalendarAdjustment, DateRoll, NamedCal, UnionCal};
7
8pub fn ndt(year: i32, month: u32, day: u32) -> NaiveDateTime {
12 NaiveDate::from_ymd_opt(year, month, day)
13 .expect("`year`, `month` `day` are invalid.")
14 .and_hms_opt(0, 0, 0)
15 .unwrap()
16}
17
18#[derive(Debug, Clone, PartialEq, FromPyObject, Serialize, Deserialize, IntoPyObject)]
20pub enum Calendar {
21 Cal(Cal),
22 UnionCal(UnionCal),
23 NamedCal(NamedCal),
24}
25
26impl From<Cal> for Calendar {
27 fn from(item: Cal) -> Self {
28 Calendar::Cal(item)
29 }
30}
31
32impl From<UnionCal> for Calendar {
33 fn from(item: UnionCal) -> Self {
34 Calendar::UnionCal(item)
35 }
36}
37
38impl From<NamedCal> for Calendar {
39 fn from(item: NamedCal) -> Self {
40 Calendar::NamedCal(item)
41 }
42}
43
44impl DateRoll for Calendar {
45 fn is_weekday(&self, date: &NaiveDateTime) -> bool {
46 match self {
47 Calendar::Cal(c) => c.is_weekday(date),
48 Calendar::UnionCal(c) => c.is_weekday(date),
49 Calendar::NamedCal(c) => c.is_weekday(date),
50 }
51 }
52
53 fn is_holiday(&self, date: &NaiveDateTime) -> bool {
54 match self {
55 Calendar::Cal(c) => c.is_holiday(date),
56 Calendar::UnionCal(c) => c.is_holiday(date),
57 Calendar::NamedCal(c) => c.is_holiday(date),
58 }
59 }
60
61 fn is_settlement(&self, date: &NaiveDateTime) -> bool {
62 match self {
63 Calendar::Cal(c) => c.is_settlement(date),
64 Calendar::UnionCal(c) => c.is_settlement(date),
65 Calendar::NamedCal(c) => c.is_settlement(date),
66 }
67 }
68}
69
70impl CalendarAdjustment for Calendar {}
71
72#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn test_docstring() {
79 let ldn = Cal::new(vec![ndt(2017, 5, 1)], vec![5, 6]); let tky = Cal::new(
81 vec![ndt(2017, 5, 3), ndt(2017, 5, 4), ndt(2017, 5, 5)],
82 vec![5, 6],
83 );
84
85 let date = ndt(2017, 4, 28); let spot = ldn.add_bus_days(&date, 2, true).unwrap();
87 assert_eq!(spot, ndt(2017, 5, 3));
88
89 let ldn_tky = UnionCal::new(vec![ldn, tky], None);
90 let spot = ldn_tky.add_bus_days(&date, 2, true).unwrap();
91 assert_eq!(spot, ndt(2017, 5, 8));
92
93 let tgt = Cal::new(vec![], vec![5, 6]);
94 let nyc = Cal::new(vec![ndt(2023, 6, 19)], vec![5, 6]); let tgt_nyc = UnionCal::new(vec![tgt], vec![nyc].into());
96
97 let date = ndt(2023, 6, 16);
98 let spot = tgt_nyc.add_bus_days(&date, 2, true).unwrap();
99 assert_eq!(spot, ndt(2023, 6, 20));
100
101 let date = ndt(2023, 6, 15);
102 let spot = tgt_nyc.add_bus_days(&date, 2, true).unwrap();
103 assert_eq!(spot, ndt(2023, 6, 20));
104
105 let spot = tgt_nyc.add_bus_days(&date, 2, false).unwrap();
106 assert_eq!(spot, ndt(2023, 6, 19));
107 }
108}