dos_date_time/dos_date_time/
convert.rs1#[cfg(feature = "chrono")]
8use chrono::NaiveDateTime;
9#[cfg(feature = "jiff")]
10use jiff::civil;
11use time::PrimitiveDateTime;
12
13use super::DateTime;
14use crate::error::DateTimeRangeError;
15
16impl From<DateTime> for PrimitiveDateTime {
17 fn from(dt: DateTime) -> Self {
37 let (date, time) = (dt.date().into(), dt.time().into());
38 Self::new(date, time)
39 }
40}
41
42#[cfg(feature = "chrono")]
43impl From<DateTime> for NaiveDateTime {
44 fn from(dt: DateTime) -> Self {
61 let (date, time) = (dt.date().into(), dt.time().into());
62 Self::new(date, time)
63 }
64}
65
66#[cfg(feature = "jiff")]
67impl From<DateTime> for civil::DateTime {
68 fn from(dt: DateTime) -> Self {
85 let (date, time) = (dt.date().into(), dt.time().into());
86 Self::from_parts(date, time)
87 }
88}
89
90impl TryFrom<PrimitiveDateTime> for DateTime {
91 type Error = DateTimeRangeError;
92
93 fn try_from(dt: PrimitiveDateTime) -> Result<Self, Self::Error> {
127 let (date, time) = (dt.date(), dt.time());
128 Self::from_date_time(date, time)
129 }
130}
131
132#[cfg(feature = "chrono")]
133impl TryFrom<NaiveDateTime> for DateTime {
134 type Error = DateTimeRangeError;
135
136 fn try_from(dt: NaiveDateTime) -> Result<Self, Self::Error> {
170 let (date, time) = (dt.date().try_into()?, dt.time().into());
171 let dt = Self::new(date, time);
172 Ok(dt)
173 }
174}
175
176#[cfg(feature = "jiff")]
177impl TryFrom<civil::DateTime> for DateTime {
178 type Error = DateTimeRangeError;
179
180 fn try_from(dt: civil::DateTime) -> Result<Self, Self::Error> {
214 let (date, time) = (dt.date().try_into()?, dt.time().into());
215 let dt = Self::new(date, time);
216 Ok(dt)
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use time::macros::datetime;
223
224 use super::*;
225 use crate::{Date, Time, error::DateTimeRangeErrorKind};
226
227 #[test]
228 fn from_date_time_to_primitive_date_time() {
229 assert_eq!(
230 PrimitiveDateTime::from(DateTime::MIN),
231 datetime!(1980-01-01 00:00:00)
232 );
233 assert_eq!(
235 PrimitiveDateTime::from(DateTime::new(
236 Date::new(0b0010_1101_0111_1010).unwrap(),
237 Time::new(0b1001_1011_0010_0000).unwrap()
238 )),
239 datetime!(2002-11-26 19:25:00)
240 );
241 assert_eq!(
243 PrimitiveDateTime::from(DateTime::new(
244 Date::new(0b0100_1101_0111_0001).unwrap(),
245 Time::new(0b0101_0100_1100_1111).unwrap()
246 )),
247 datetime!(2018-11-17 10:38:30)
248 );
249 assert_eq!(
250 PrimitiveDateTime::from(DateTime::MAX),
251 datetime!(2107-12-31 23:59:58)
252 );
253 }
254
255 #[cfg(feature = "chrono")]
256 #[test]
257 fn from_date_time_to_chrono_naive_date_time() {
258 assert_eq!(
259 NaiveDateTime::from(DateTime::MIN),
260 "1980-01-01T00:00:00".parse::<NaiveDateTime>().unwrap()
261 );
262 assert_eq!(
264 NaiveDateTime::from(DateTime::new(
265 Date::new(0b0010_1101_0111_1010).unwrap(),
266 Time::new(0b1001_1011_0010_0000).unwrap()
267 )),
268 "2002-11-26T19:25:00".parse::<NaiveDateTime>().unwrap()
269 );
270 assert_eq!(
272 NaiveDateTime::from(DateTime::new(
273 Date::new(0b0100_1101_0111_0001).unwrap(),
274 Time::new(0b0101_0100_1100_1111).unwrap()
275 )),
276 "2018-11-17T10:38:30".parse::<NaiveDateTime>().unwrap()
277 );
278 assert_eq!(
279 NaiveDateTime::from(DateTime::MAX),
280 "2107-12-31T23:59:58".parse::<NaiveDateTime>().unwrap()
281 );
282 }
283
284 #[cfg(feature = "jiff")]
285 #[test]
286 fn from_date_time_to_jiff_civil_date_time() {
287 assert_eq!(
288 civil::DateTime::from(DateTime::MIN),
289 civil::date(1980, 1, 1).at(0, 0, 0, 0)
290 );
291 assert_eq!(
293 civil::DateTime::from(DateTime::new(
294 Date::new(0b0010_1101_0111_1010).unwrap(),
295 Time::new(0b1001_1011_0010_0000).unwrap()
296 )),
297 civil::date(2002, 11, 26).at(19, 25, 0, 0)
298 );
299 assert_eq!(
301 civil::DateTime::from(DateTime::new(
302 Date::new(0b0100_1101_0111_0001).unwrap(),
303 Time::new(0b0101_0100_1100_1111).unwrap()
304 )),
305 civil::date(2018, 11, 17).at(10, 38, 30, 0)
306 );
307 assert_eq!(
308 civil::DateTime::from(DateTime::MAX),
309 civil::date(2107, 12, 31).at(23, 59, 58, 0)
310 );
311 }
312
313 #[test]
314 fn try_from_primitive_date_time_to_date_time_before_dos_date_time_epoch() {
315 assert_eq!(
316 DateTime::try_from(datetime!(1979-12-31 23:59:58)).unwrap_err(),
317 DateTimeRangeErrorKind::Negative.into()
318 );
319 assert_eq!(
320 DateTime::try_from(datetime!(1979-12-31 23:59:59)).unwrap_err(),
321 DateTimeRangeErrorKind::Negative.into()
322 );
323 }
324
325 #[test]
326 fn try_from_primitive_date_time_to_date_time() {
327 assert_eq!(
328 DateTime::try_from(datetime!(1980-01-01 00:00:00)).unwrap(),
329 DateTime::MIN
330 );
331 assert_eq!(
332 DateTime::try_from(datetime!(1980-01-01 00:00:01)).unwrap(),
333 DateTime::MIN
334 );
335 assert_eq!(
337 DateTime::try_from(datetime!(2002-11-26 19:25:00)).unwrap(),
338 DateTime::new(
339 Date::new(0b0010_1101_0111_1010).unwrap(),
340 Time::new(0b1001_1011_0010_0000).unwrap()
341 )
342 );
343 assert_eq!(
345 DateTime::try_from(datetime!(2018-11-17 10:38:30)).unwrap(),
346 DateTime::new(
347 Date::new(0b0100_1101_0111_0001).unwrap(),
348 Time::new(0b0101_0100_1100_1111).unwrap()
349 )
350 );
351 assert_eq!(
352 DateTime::try_from(datetime!(2107-12-31 23:59:58)).unwrap(),
353 DateTime::MAX
354 );
355 assert_eq!(
356 DateTime::try_from(datetime!(2107-12-31 23:59:59)).unwrap(),
357 DateTime::MAX
358 );
359 }
360
361 #[test]
362 fn try_from_primitive_date_time_to_date_time_with_too_big_date_time() {
363 assert_eq!(
364 DateTime::try_from(datetime!(2108-01-01 00:00:00)).unwrap_err(),
365 DateTimeRangeErrorKind::Overflow.into()
366 );
367 }
368
369 #[cfg(feature = "chrono")]
370 #[test]
371 fn try_from_chrono_naive_date_time_to_date_time_before_dos_date_time_epoch() {
372 assert_eq!(
373 DateTime::try_from("1979-12-31T23:59:58".parse::<NaiveDateTime>().unwrap())
374 .unwrap_err(),
375 DateTimeRangeErrorKind::Negative.into()
376 );
377 assert_eq!(
378 DateTime::try_from("1979-12-31T23:59:59".parse::<NaiveDateTime>().unwrap())
379 .unwrap_err(),
380 DateTimeRangeErrorKind::Negative.into()
381 );
382 }
383
384 #[cfg(feature = "chrono")]
385 #[test]
386 fn try_from_chrono_naive_date_time_to_date_time() {
387 assert_eq!(
388 DateTime::try_from("1980-01-01T00:00:00".parse::<NaiveDateTime>().unwrap()).unwrap(),
389 DateTime::MIN
390 );
391 assert_eq!(
392 DateTime::try_from("1980-01-01T00:00:01".parse::<NaiveDateTime>().unwrap()).unwrap(),
393 DateTime::MIN
394 );
395 assert_eq!(
397 DateTime::try_from("2002-11-26T19:25:00".parse::<NaiveDateTime>().unwrap()).unwrap(),
398 DateTime::new(
399 Date::new(0b0010_1101_0111_1010).unwrap(),
400 Time::new(0b1001_1011_0010_0000).unwrap()
401 )
402 );
403 assert_eq!(
405 DateTime::try_from("2018-11-17T10:38:30".parse::<NaiveDateTime>().unwrap()).unwrap(),
406 DateTime::new(
407 Date::new(0b0100_1101_0111_0001).unwrap(),
408 Time::new(0b0101_0100_1100_1111).unwrap()
409 )
410 );
411 assert_eq!(
412 DateTime::try_from("2107-12-31T23:59:58".parse::<NaiveDateTime>().unwrap()).unwrap(),
413 DateTime::MAX
414 );
415 assert_eq!(
416 DateTime::try_from("2107-12-31T23:59:59".parse::<NaiveDateTime>().unwrap()).unwrap(),
417 DateTime::MAX
418 );
419 }
420
421 #[cfg(feature = "chrono")]
422 #[test]
423 fn try_from_chrono_naive_date_time_to_date_time_with_too_big_date_time() {
424 assert_eq!(
425 DateTime::try_from("2108-01-01T00:00:00".parse::<NaiveDateTime>().unwrap())
426 .unwrap_err(),
427 DateTimeRangeErrorKind::Overflow.into()
428 );
429 }
430
431 #[cfg(feature = "jiff")]
432 #[test]
433 fn try_from_jiff_civil_date_time_to_date_time_before_dos_date_time_epoch() {
434 assert_eq!(
435 DateTime::try_from(civil::date(1979, 12, 31).at(23, 59, 58, 0)).unwrap_err(),
436 DateTimeRangeErrorKind::Negative.into()
437 );
438 assert_eq!(
439 DateTime::try_from(civil::date(1979, 12, 31).at(23, 59, 59, 0)).unwrap_err(),
440 DateTimeRangeErrorKind::Negative.into()
441 );
442 }
443
444 #[cfg(feature = "jiff")]
445 #[test]
446 fn try_from_jiff_civil_date_time_to_date_time() {
447 assert_eq!(
448 DateTime::try_from(civil::date(1980, 1, 1).at(0, 0, 0, 0)).unwrap(),
449 DateTime::MIN
450 );
451 assert_eq!(
452 DateTime::try_from(civil::date(1980, 1, 1).at(0, 0, 1, 0)).unwrap(),
453 DateTime::MIN
454 );
455 assert_eq!(
457 DateTime::try_from(civil::date(2002, 11, 26).at(19, 25, 0, 0)).unwrap(),
458 DateTime::new(
459 Date::new(0b0010_1101_0111_1010).unwrap(),
460 Time::new(0b1001_1011_0010_0000).unwrap()
461 )
462 );
463 assert_eq!(
465 DateTime::try_from(civil::date(2018, 11, 17).at(10, 38, 30, 0)).unwrap(),
466 DateTime::new(
467 Date::new(0b0100_1101_0111_0001).unwrap(),
468 Time::new(0b0101_0100_1100_1111).unwrap()
469 )
470 );
471 assert_eq!(
472 DateTime::try_from(civil::date(2107, 12, 31).at(23, 59, 58, 0)).unwrap(),
473 DateTime::MAX
474 );
475 assert_eq!(
476 DateTime::try_from(civil::date(2107, 12, 31).at(23, 59, 59, 0)).unwrap(),
477 DateTime::MAX
478 );
479 }
480
481 #[cfg(feature = "jiff")]
482 #[test]
483 fn try_from_jiff_civil_date_time_to_date_time_with_too_big_date_time() {
484 assert_eq!(
485 DateTime::try_from(civil::date(2108, 1, 1).at(0, 0, 0, 0)).unwrap_err(),
486 DateTimeRangeErrorKind::Overflow.into()
487 );
488 }
489}