1use crate::{Dt, Scale};
2use chrono::{DateTime, Datelike, Duration, TimeDelta, Timelike, Utc};
3
4#[inline]
6fn clamp_i128_to_u64(x: i128) -> u64 {
7 if x > u64::MAX as i128 {
8 u64::MAX
9 } else if x < u64::MIN as i128 {
10 u64::MIN
11 } else {
12 x as u64
13 }
14}
15
16impl Dt {
17 pub fn from_chrono_datetime_utc(dt: DateTime<Utc>) -> Self {
21 let yr = dt.year() as i64;
22 let mo = dt.month().clamp(1, 12) as u8;
23 let day = dt.day().clamp(1, 31) as u8;
24 let hr = dt.hour().clamp(0, 23) as u8;
25 let min = dt.minute().clamp(0, 59) as u8;
26 let sec = dt.second().clamp(0, 60) as u8;
27 let subsec_nanos = dt.nanosecond();
28 let attos = Dt::from_ns(subsec_nanos as i128, Scale::TAI).to_attos();
29
30 Dt::from_ymdhms_on(
31 yr,
32 mo,
33 day,
34 hr,
35 min,
36 sec,
37 clamp_i128_to_u64(attos),
38 Scale::UTC,
39 )
40 }
41
42 pub fn from_chrono_duration(dur: Duration) -> Self {
44 match dur.num_nanoseconds() {
45 Some(ns) => Self::from_ns(ns as i128, Scale::TAI),
46 None => {
47 let ns = if dur > Duration::zero() {
48 i64::MAX
49 } else {
50 i64::MIN
51 };
52 Self::from_ns(ns as i128, Scale::TAI)
53 }
54 }
55 }
56
57 #[inline]
63 pub fn to_chrono_datetime_utc(&self, current: Scale) -> DateTime<Utc> {
64 DateTime::<Utc>::from_timestamp_nanos(Dt::clamp_i128_to_i64(
65 self.to_unix(current, Scale::UTC).to_ns(),
66 ))
67 }
68
69 #[inline]
76 pub fn to_chrono_duration(&self) -> Duration {
77 TimeDelta::nanoseconds(Dt::clamp_i128_to_i64(self.to_ns()))
78 }
79}