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 u16 {
16 fn from(date: Date) -> Self {
17 date.to_raw()
18 }
19}
20
21impl From<Date> for time::Date {
22 fn from(date: Date) -> Self {
33 let (year, month, day) = (date.year().into(), date.month(), date.day());
34 Self::from_calendar_date(year, month, day)
35 .expect("date should be in the range of `time::Date`")
36 }
37}
38
39#[cfg(feature = "chrono")]
40impl From<Date> for NaiveDate {
41 fn from(date: Date) -> Self {
58 let (year, month, day) = (
59 date.year().into(),
60 u8::from(date.month()).into(),
61 date.day().into(),
62 );
63 Self::from_ymd_opt(year, month, day).expect("date should be in the range of `NaiveDate`")
64 }
65}
66
67#[cfg(feature = "jiff")]
68impl From<Date> for civil::Date {
69 fn from(date: Date) -> Self {
80 let (year, month, day) = (
81 date.year()
82 .try_into()
83 .expect("year should be in the range of `i16`"),
84 u8::from(date.month())
85 .try_into()
86 .expect("month should be in the range of `i8`"),
87 date.day()
88 .try_into()
89 .expect("day should be in the range of `i8`"),
90 );
91 civil::date(year, month, day)
92 }
93}
94
95impl TryFrom<time::Date> for Date {
96 type Error = DateRangeError;
97
98 fn try_from(date: time::Date) -> Result<Self, Self::Error> {
118 Self::from_date(date)
119 }
120}
121
122#[cfg(feature = "chrono")]
123impl TryFrom<NaiveDate> for Date {
124 type Error = DateRangeError;
125
126 fn try_from(date: NaiveDate) -> Result<Self, Self::Error> {
152 let (year, month, day) = (
153 date.year(),
154 u8::try_from(date.month())
155 .expect("month should be in the range of `u8`")
156 .try_into()
157 .expect("month should be in the range of `Month`"),
158 date.day()
159 .try_into()
160 .expect("day should be in the range of `u8`"),
161 );
162 let date = time::Date::from_calendar_date(year, month, day)
163 .expect("date should be in the range of `time::Date`");
164 Self::from_date(date)
165 }
166}
167
168#[cfg(feature = "jiff")]
169impl TryFrom<civil::Date> for Date {
170 type Error = DateRangeError;
171
172 fn try_from(date: civil::Date) -> Result<Self, Self::Error> {
192 let (year, month, day) = (
193 date.year().into(),
194 u8::try_from(date.month())
195 .expect("month should be in the range of `u8`")
196 .try_into()
197 .expect("month should be in the range of `Month`"),
198 date.day()
199 .try_into()
200 .expect("day should be in the range of `u8`"),
201 );
202 let date = time::Date::from_calendar_date(year, month, day)
203 .expect("date should be in the range of `time::Date`");
204 Self::from_date(date)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use time::macros::date;
211
212 use super::*;
213 use crate::error::DateRangeErrorKind;
214
215 #[test]
216 fn from_date_to_u16() {
217 assert_eq!(u16::from(Date::MIN), 0b0000_0000_0010_0001);
218 assert_eq!(
220 u16::from(Date::new(0b0010_1101_0111_1010).unwrap()),
221 0b0010_1101_0111_1010
222 );
223 assert_eq!(
225 u16::from(Date::new(0b0100_1101_0111_0001).unwrap()),
226 0b0100_1101_0111_0001
227 );
228 assert_eq!(u16::from(Date::MAX), 0b1111_1111_1001_1111);
229 }
230
231 #[test]
232 fn from_date_to_time_date() {
233 assert_eq!(time::Date::from(Date::MIN), date!(1980-01-01));
234 assert_eq!(
236 time::Date::from(Date::new(0b0010_1101_0111_1010).unwrap()),
237 date!(2002-11-26)
238 );
239 assert_eq!(
241 time::Date::from(Date::new(0b0100_1101_0111_0001).unwrap()),
242 date!(2018-11-17)
243 );
244 assert_eq!(time::Date::from(Date::MAX), date!(2107-12-31));
245 }
246
247 #[cfg(feature = "chrono")]
248 #[test]
249 fn from_date_to_chrono_naive_date() {
250 assert_eq!(
251 NaiveDate::from(Date::MIN),
252 "1980-01-01".parse::<NaiveDate>().unwrap()
253 );
254 assert_eq!(
256 NaiveDate::from(Date::new(0b0010_1101_0111_1010).unwrap()),
257 "2002-11-26".parse::<NaiveDate>().unwrap()
258 );
259 assert_eq!(
261 NaiveDate::from(Date::new(0b0100_1101_0111_0001).unwrap()),
262 "2018-11-17".parse::<NaiveDate>().unwrap()
263 );
264 assert_eq!(
265 NaiveDate::from(Date::MAX),
266 "2107-12-31".parse::<NaiveDate>().unwrap()
267 );
268 }
269
270 #[cfg(feature = "jiff")]
271 #[test]
272 fn from_date_to_jiff_civil_date() {
273 assert_eq!(civil::Date::from(Date::MIN), civil::date(1980, 1, 1));
274 assert_eq!(
276 civil::Date::from(Date::new(0b0010_1101_0111_1010).unwrap()),
277 civil::date(2002, 11, 26)
278 );
279 assert_eq!(
281 civil::Date::from(Date::new(0b0100_1101_0111_0001).unwrap()),
282 civil::date(2018, 11, 17)
283 );
284 assert_eq!(civil::Date::from(Date::MAX), civil::date(2107, 12, 31));
285 }
286
287 #[test]
288 fn try_from_time_date_to_date_before_dos_date_epoch() {
289 assert_eq!(
290 Date::try_from(date!(1979-12-31)).unwrap_err(),
291 DateRangeErrorKind::Negative.into()
292 );
293 assert_eq!(
294 Date::try_from(date!(1979-12-31)).unwrap_err(),
295 DateRangeErrorKind::Negative.into()
296 );
297 }
298
299 #[test]
300 fn try_from_time_date_to_date() {
301 assert_eq!(Date::try_from(date!(1980-01-01)).unwrap(), Date::MIN);
302 assert_eq!(Date::try_from(date!(1980-01-01)).unwrap(), Date::MIN);
303 assert_eq!(
305 Date::try_from(date!(2002-11-26)).unwrap(),
306 Date::new(0b0010_1101_0111_1010).unwrap()
307 );
308 assert_eq!(
310 Date::try_from(date!(2018-11-17)).unwrap(),
311 Date::new(0b0100_1101_0111_0001).unwrap()
312 );
313 assert_eq!(Date::try_from(date!(2107-12-31)).unwrap(), Date::MAX);
314 assert_eq!(Date::try_from(date!(2107-12-31)).unwrap(), Date::MAX);
315 }
316
317 #[test]
318 fn try_from_time_date_to_date_with_too_big_date() {
319 assert_eq!(
320 Date::try_from(date!(2108-01-01)).unwrap_err(),
321 DateRangeErrorKind::Overflow.into()
322 );
323 }
324
325 #[cfg(feature = "chrono")]
326 #[test]
327 fn try_from_chrono_naive_date_to_date_before_dos_date_epoch() {
328 assert_eq!(
329 Date::try_from("1979-12-31".parse::<NaiveDate>().unwrap()).unwrap_err(),
330 DateRangeErrorKind::Negative.into()
331 );
332 assert_eq!(
333 Date::try_from("1979-12-31".parse::<NaiveDate>().unwrap()).unwrap_err(),
334 DateRangeErrorKind::Negative.into()
335 );
336 }
337
338 #[cfg(feature = "chrono")]
339 #[test]
340 fn try_from_chrono_naive_date_to_date() {
341 assert_eq!(
342 Date::try_from("1980-01-01".parse::<NaiveDate>().unwrap()).unwrap(),
343 Date::MIN
344 );
345 assert_eq!(
346 Date::try_from("1980-01-01".parse::<NaiveDate>().unwrap()).unwrap(),
347 Date::MIN
348 );
349 assert_eq!(
351 Date::try_from("2002-11-26".parse::<NaiveDate>().unwrap()).unwrap(),
352 Date::new(0b0010_1101_0111_1010).unwrap()
353 );
354 assert_eq!(
356 Date::try_from("2018-11-17".parse::<NaiveDate>().unwrap()).unwrap(),
357 Date::new(0b0100_1101_0111_0001).unwrap()
358 );
359 assert_eq!(
360 Date::try_from("2107-12-31".parse::<NaiveDate>().unwrap()).unwrap(),
361 Date::MAX
362 );
363 assert_eq!(
364 Date::try_from("2107-12-31".parse::<NaiveDate>().unwrap()).unwrap(),
365 Date::MAX
366 );
367 }
368
369 #[cfg(feature = "chrono")]
370 #[test]
371 fn try_from_chrono_naive_date_to_date_with_too_big_date() {
372 assert_eq!(
373 Date::try_from("2108-01-01".parse::<NaiveDate>().unwrap()).unwrap_err(),
374 DateRangeErrorKind::Overflow.into()
375 );
376 }
377
378 #[cfg(feature = "jiff")]
379 #[test]
380 fn try_from_jiff_civil_date_to_date_before_dos_date_epoch() {
381 assert_eq!(
382 Date::try_from(civil::date(1979, 12, 31)).unwrap_err(),
383 DateRangeErrorKind::Negative.into()
384 );
385 assert_eq!(
386 Date::try_from(civil::date(1979, 12, 31)).unwrap_err(),
387 DateRangeErrorKind::Negative.into()
388 );
389 }
390
391 #[cfg(feature = "jiff")]
392 #[test]
393 fn try_from_jiff_civil_date_to_date() {
394 assert_eq!(Date::try_from(civil::date(1980, 1, 1)).unwrap(), Date::MIN);
395 assert_eq!(Date::try_from(civil::date(1980, 1, 1)).unwrap(), Date::MIN);
396 assert_eq!(
398 Date::try_from(civil::date(2002, 11, 26)).unwrap(),
399 Date::new(0b0010_1101_0111_1010).unwrap()
400 );
401 assert_eq!(
403 Date::try_from(civil::date(2018, 11, 17)).unwrap(),
404 Date::new(0b0100_1101_0111_0001).unwrap()
405 );
406 assert_eq!(
407 Date::try_from(civil::date(2107, 12, 31)).unwrap(),
408 Date::MAX
409 );
410 assert_eq!(
411 Date::try_from(civil::date(2107, 12, 31)).unwrap(),
412 Date::MAX
413 );
414 }
415
416 #[cfg(feature = "jiff")]
417 #[test]
418 fn try_from_jiff_civil_date_to_date_with_too_big_date() {
419 assert_eq!(
420 Date::try_from(civil::date(2108, 1, 1)).unwrap_err(),
421 DateRangeErrorKind::Overflow.into()
422 );
423 }
424}