1#[cfg(feature = "chrono")]
8use chrono::{Datelike, NaiveDate};
9#[cfg(feature = "jiff")]
10use jiff::civil;
11
12use super::Date;
13use crate::error::DateRangeError;
14
15impl From<Date> for time::Date {
16 fn from(date: Date) -> Self {
27 let (year, month, day) = (date.year().into(), date.month(), date.day());
28 Self::from_calendar_date(year, month, day)
29 .expect("date should be in the range of `time::Date`")
30 }
31}
32
33#[cfg(feature = "chrono")]
34impl From<Date> for NaiveDate {
35 fn from(date: Date) -> Self {
52 let (year, month, day) = (
53 date.year().into(),
54 u8::from(date.month()).into(),
55 date.day().into(),
56 );
57 Self::from_ymd_opt(year, month, day).expect("date should be in the range of `NaiveDate`")
58 }
59}
60
61#[cfg(feature = "jiff")]
62impl From<Date> for civil::Date {
63 fn from(date: Date) -> Self {
74 let (year, month, day) = (
75 date.year()
76 .try_into()
77 .expect("year should be in the range of `i16`"),
78 u8::from(date.month())
79 .try_into()
80 .expect("month should be in the range of `i8`"),
81 date.day()
82 .try_into()
83 .expect("day should be in the range of `i8`"),
84 );
85 civil::date(year, month, day)
86 }
87}
88
89impl TryFrom<time::Date> for Date {
90 type Error = DateRangeError;
91
92 fn try_from(date: time::Date) -> Result<Self, Self::Error> {
112 Self::from_date(date)
113 }
114}
115
116#[cfg(feature = "chrono")]
117impl TryFrom<NaiveDate> for Date {
118 type Error = DateRangeError;
119
120 fn try_from(date: NaiveDate) -> Result<Self, Self::Error> {
146 let (year, month, day) = (
147 date.year(),
148 u8::try_from(date.month())
149 .expect("month should be in the range of `u8`")
150 .try_into()
151 .expect("month should be in the range of `Month`"),
152 date.day()
153 .try_into()
154 .expect("day should be in the range of `u8`"),
155 );
156 let date = time::Date::from_calendar_date(year, month, day)
157 .expect("date should be in the range of `time::Date`");
158 Self::from_date(date)
159 }
160}
161
162#[cfg(feature = "jiff")]
163impl TryFrom<civil::Date> for Date {
164 type Error = DateRangeError;
165
166 fn try_from(date: civil::Date) -> Result<Self, Self::Error> {
186 let (year, month, day) = (
187 date.year().into(),
188 u8::try_from(date.month())
189 .expect("month should be in the range of `u8`")
190 .try_into()
191 .expect("month should be in the range of `Month`"),
192 date.day()
193 .try_into()
194 .expect("day should be in the range of `u8`"),
195 );
196 let date = time::Date::from_calendar_date(year, month, day)
197 .expect("date should be in the range of `time::Date`");
198 Self::from_date(date)
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use time::macros::date;
205
206 use super::*;
207 use crate::error::DateRangeErrorKind;
208
209 #[test]
210 fn from_date_to_time_date() {
211 assert_eq!(time::Date::from(Date::MIN), date!(1980-01-01));
212 assert_eq!(
214 time::Date::from(Date::new(0b0010_1101_0111_1010).unwrap()),
215 date!(2002-11-26)
216 );
217 assert_eq!(
219 time::Date::from(Date::new(0b0100_1101_0111_0001).unwrap()),
220 date!(2018-11-17)
221 );
222 assert_eq!(time::Date::from(Date::MAX), date!(2107-12-31));
223 }
224
225 #[cfg(feature = "chrono")]
226 #[test]
227 fn from_date_to_chrono_naive_date() {
228 assert_eq!(
229 NaiveDate::from(Date::MIN),
230 "1980-01-01".parse::<NaiveDate>().unwrap()
231 );
232 assert_eq!(
234 NaiveDate::from(Date::new(0b0010_1101_0111_1010).unwrap()),
235 "2002-11-26".parse::<NaiveDate>().unwrap()
236 );
237 assert_eq!(
239 NaiveDate::from(Date::new(0b0100_1101_0111_0001).unwrap()),
240 "2018-11-17".parse::<NaiveDate>().unwrap()
241 );
242 assert_eq!(
243 NaiveDate::from(Date::MAX),
244 "2107-12-31".parse::<NaiveDate>().unwrap()
245 );
246 }
247
248 #[cfg(feature = "jiff")]
249 #[test]
250 fn from_date_to_jiff_civil_date() {
251 assert_eq!(civil::Date::from(Date::MIN), civil::date(1980, 1, 1));
252 assert_eq!(
254 civil::Date::from(Date::new(0b0010_1101_0111_1010).unwrap()),
255 civil::date(2002, 11, 26)
256 );
257 assert_eq!(
259 civil::Date::from(Date::new(0b0100_1101_0111_0001).unwrap()),
260 civil::date(2018, 11, 17)
261 );
262 assert_eq!(civil::Date::from(Date::MAX), civil::date(2107, 12, 31));
263 }
264
265 #[test]
266 fn try_from_time_date_to_date_before_dos_date_epoch() {
267 assert_eq!(
268 Date::try_from(date!(1979-12-31)).unwrap_err(),
269 DateRangeErrorKind::Negative.into()
270 );
271 assert_eq!(
272 Date::try_from(date!(1979-12-31)).unwrap_err(),
273 DateRangeErrorKind::Negative.into()
274 );
275 }
276
277 #[test]
278 fn try_from_time_date_to_date() {
279 assert_eq!(Date::try_from(date!(1980-01-01)).unwrap(), Date::MIN);
280 assert_eq!(Date::try_from(date!(1980-01-01)).unwrap(), Date::MIN);
281 assert_eq!(
283 Date::try_from(date!(2002-11-26)).unwrap(),
284 Date::new(0b0010_1101_0111_1010).unwrap()
285 );
286 assert_eq!(
288 Date::try_from(date!(2018-11-17)).unwrap(),
289 Date::new(0b0100_1101_0111_0001).unwrap()
290 );
291 assert_eq!(Date::try_from(date!(2107-12-31)).unwrap(), Date::MAX);
292 assert_eq!(Date::try_from(date!(2107-12-31)).unwrap(), Date::MAX);
293 }
294
295 #[test]
296 fn try_from_time_date_to_date_with_too_big_date() {
297 assert_eq!(
298 Date::try_from(date!(2108-01-01)).unwrap_err(),
299 DateRangeErrorKind::Overflow.into()
300 );
301 }
302
303 #[cfg(feature = "chrono")]
304 #[test]
305 fn try_from_chrono_naive_date_to_date_before_dos_date_epoch() {
306 assert_eq!(
307 Date::try_from("1979-12-31".parse::<NaiveDate>().unwrap()).unwrap_err(),
308 DateRangeErrorKind::Negative.into()
309 );
310 assert_eq!(
311 Date::try_from("1979-12-31".parse::<NaiveDate>().unwrap()).unwrap_err(),
312 DateRangeErrorKind::Negative.into()
313 );
314 }
315
316 #[cfg(feature = "chrono")]
317 #[test]
318 fn try_from_chrono_naive_date_to_date() {
319 assert_eq!(
320 Date::try_from("1980-01-01".parse::<NaiveDate>().unwrap()).unwrap(),
321 Date::MIN
322 );
323 assert_eq!(
324 Date::try_from("1980-01-01".parse::<NaiveDate>().unwrap()).unwrap(),
325 Date::MIN
326 );
327 assert_eq!(
329 Date::try_from("2002-11-26".parse::<NaiveDate>().unwrap()).unwrap(),
330 Date::new(0b0010_1101_0111_1010).unwrap()
331 );
332 assert_eq!(
334 Date::try_from("2018-11-17".parse::<NaiveDate>().unwrap()).unwrap(),
335 Date::new(0b0100_1101_0111_0001).unwrap()
336 );
337 assert_eq!(
338 Date::try_from("2107-12-31".parse::<NaiveDate>().unwrap()).unwrap(),
339 Date::MAX
340 );
341 assert_eq!(
342 Date::try_from("2107-12-31".parse::<NaiveDate>().unwrap()).unwrap(),
343 Date::MAX
344 );
345 }
346
347 #[cfg(feature = "chrono")]
348 #[test]
349 fn try_from_chrono_naive_date_to_date_with_too_big_date() {
350 assert_eq!(
351 Date::try_from("2108-01-01".parse::<NaiveDate>().unwrap()).unwrap_err(),
352 DateRangeErrorKind::Overflow.into()
353 );
354 }
355
356 #[cfg(feature = "jiff")]
357 #[test]
358 fn try_from_jiff_civil_date_to_date_before_dos_date_epoch() {
359 assert_eq!(
360 Date::try_from(civil::date(1979, 12, 31)).unwrap_err(),
361 DateRangeErrorKind::Negative.into()
362 );
363 assert_eq!(
364 Date::try_from(civil::date(1979, 12, 31)).unwrap_err(),
365 DateRangeErrorKind::Negative.into()
366 );
367 }
368
369 #[cfg(feature = "jiff")]
370 #[test]
371 fn try_from_jiff_civil_date_to_date() {
372 assert_eq!(Date::try_from(civil::date(1980, 1, 1)).unwrap(), Date::MIN);
373 assert_eq!(Date::try_from(civil::date(1980, 1, 1)).unwrap(), Date::MIN);
374 assert_eq!(
376 Date::try_from(civil::date(2002, 11, 26)).unwrap(),
377 Date::new(0b0010_1101_0111_1010).unwrap()
378 );
379 assert_eq!(
381 Date::try_from(civil::date(2018, 11, 17)).unwrap(),
382 Date::new(0b0100_1101_0111_0001).unwrap()
383 );
384 assert_eq!(
385 Date::try_from(civil::date(2107, 12, 31)).unwrap(),
386 Date::MAX
387 );
388 assert_eq!(
389 Date::try_from(civil::date(2107, 12, 31)).unwrap(),
390 Date::MAX
391 );
392 }
393
394 #[cfg(feature = "jiff")]
395 #[test]
396 fn try_from_jiff_civil_date_to_date_with_too_big_date() {
397 assert_eq!(
398 Date::try_from(civil::date(2108, 1, 1)).unwrap_err(),
399 DateRangeErrorKind::Overflow.into()
400 );
401 }
402}