jp_holidays_lib/
client.rs1use chrono::{Datelike, NaiveDate};
4
5pub struct Client {
21 data: std::collections::BTreeMap<NaiveDate, String>,
22}
23
24impl Client {
25 #[doc = include_str!("../examples/basic.rs")]
31 #[doc = include_str!("../examples/cache.rs")]
39 pub async fn init() -> Result<Self, crate::error::Error> {
41 let holiday_repository = std::sync::Arc::new(crate::repository::HolidayRepositoryImpl);
42 let holiday_service =
43 std::sync::Arc::new(crate::service::HolidayService { holiday_repository });
44 let shiftjis_bytes = holiday_service.fetch_shiftjis_csv_bytes().await?;
45 let csv = holiday_service.parse_csv(shiftjis_bytes).await?;
46 let data = holiday_service.deserialize_csv(&csv)?;
47 Ok(Self { data })
48 }
49
50 #[cfg(test)]
51 async fn init_stub() -> Result<Self, crate::error::Error> {
52 let holiday_repository = std::sync::Arc::new(crate::repository::HolidayRepositoryStub);
53 let holiday_service =
54 std::sync::Arc::new(crate::service::HolidayService { holiday_repository });
55 let shiftjis_bytes = holiday_service.fetch_shiftjis_csv_bytes().await?;
56 let csv = holiday_service.parse_csv(shiftjis_bytes).await?;
57 let data = holiday_service.deserialize_csv(&csv)?;
58 Ok(Self { data })
59 }
60
61 #[doc = include_str!("../examples/list_holidays.rs")]
67 pub fn list_holidays(&self) -> &std::collections::BTreeMap<NaiveDate, String> {
69 &self.data
70 }
71
72 #[doc = include_str!("../examples/get_holiday.rs")]
78 pub fn get_holiday(&self, date: NaiveDate) -> Option<&str> {
80 self.data.get(&date).map(|s| s.as_str())
81 }
82
83 #[doc = include_str!("../examples/get_holiday_ymd.rs")]
88 pub fn get_holiday_ymd(
90 &self,
91 year: i32,
92 month: u32,
93 day: u32,
94 ) -> Result<Option<&str>, crate::error::Error> {
95 let date =
96 NaiveDate::from_ymd_opt(year, month, day).ok_or(crate::error::Error::InvalidDate(
97 format!("不正な日付です: {}年 {}月 {}日", year, month, day),
98 ))?;
99 Ok(self.get_holiday(date))
100 }
101
102 #[doc = include_str!("../examples/is_holiday.rs")]
108 pub fn is_holiday(&self, date: NaiveDate) -> bool {
110 self.data.contains_key(&date)
111 }
112
113 #[doc = include_str!("../examples/is_holiday_ymd.rs")]
119 pub fn is_holiday_ymd(
121 &self,
122 year: i32,
123 month: u32,
124 day: u32,
125 ) -> Result<bool, crate::error::Error> {
126 let date =
127 NaiveDate::from_ymd_opt(year, month, day).ok_or(crate::error::Error::InvalidDate(
128 format!("不正な日付です: {}年 {}月 {}日", year, month, day),
129 ))?;
130 Ok(self.is_holiday(date))
131 }
132
133 #[doc = include_str!("../examples/is_day_off.rs")]
139 pub fn is_day_off(&self, date: NaiveDate) -> bool {
141 matches!(date.weekday(), chrono::Weekday::Sat | chrono::Weekday::Sun)
142 || self.is_holiday(date)
143 }
144
145 #[doc = include_str!("../examples/is_day_off_ymd.rs")]
151 pub fn is_day_off_ymd(
153 &self,
154 year: i32,
155 month: u32,
156 day: u32,
157 ) -> Result<bool, crate::error::Error> {
158 let date =
159 NaiveDate::from_ymd_opt(year, month, day).ok_or(crate::error::Error::InvalidDate(
160 format!("不正な日付です: {}年 {}月 {}日", year, month, day),
161 ))?;
162 Ok(self.is_day_off(date))
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[tokio::test]
171 async fn test_get_holiday_known_date() {
172 let client = Client::init_stub().await.unwrap();
173 let holiday = client.get_holiday_ymd(1955, 1, 1).unwrap();
174 assert_eq!(holiday, Some("元日"));
175 }
176
177 #[tokio::test]
178 async fn test_get_holiday_unknown_date() {
179 let client = Client::init_stub().await.unwrap();
180 let holiday = client.get_holiday_ymd(1955, 1, 2).unwrap();
181 assert_eq!(holiday, None);
182 }
183
184 #[tokio::test]
185 async fn test_is_holiday_true() {
186 let client = Client::init_stub().await.unwrap();
187 let is_holiday = client.is_holiday_ymd(1955, 5, 5).unwrap();
188 assert!(is_holiday);
189 }
190
191 #[tokio::test]
192 async fn test_is_holiday_false() {
193 let client = Client::init_stub().await.unwrap();
194 let is_holiday = client.is_holiday_ymd(1955, 5, 4).unwrap();
195 assert!(!is_holiday);
196 }
197
198 #[tokio::test]
199 async fn test_invalid_date() {
200 let client = Client::init_stub().await.unwrap();
201 let result = client.get_holiday_ymd(1955, 2, 30);
202 assert!(result.is_err());
203 }
204
205 #[tokio::test]
206 async fn test_is_day_off_holiday() {
207 let client = Client::init_stub().await.unwrap();
208 let is_day_off = client.is_day_off_ymd(1955, 1, 1).unwrap();
209 assert!(is_day_off);
210 }
211
212 #[tokio::test]
213 async fn test_is_day_off_weekend() {
214 let client = Client::init_stub().await.unwrap();
215 let is_day_off = client.is_day_off_ymd(1955, 1, 8).unwrap();
216 assert!(is_day_off);
217 }
218
219 #[tokio::test]
220 async fn test_is_day_off_weekday_non_holiday() {
221 let client = Client::init_stub().await.unwrap();
222 let is_day_off = client.is_day_off_ymd(1955, 1, 5).unwrap();
223 assert!(!is_day_off);
224 }
225}