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 #[inline]
23 pub fn to_chrono_datetime_utc(&self, current: Scale) -> DateTime<Utc> {
24 DateTime::<Utc>::from_timestamp_nanos(Dt::clamp_i128_to_i64(
25 self.to_unix(current, Scale::UTC).to_ns(),
26 ))
27 }
28
29 pub fn from_chrono_datetime_utc(dt: DateTime<Utc>) -> Self {
33 let yr = dt.year() as i64;
34 let mo = dt.month().clamp(1, 12) as u8;
35 let day = dt.day().clamp(1, 31) as u8;
36 let hr = dt.hour().clamp(0, 23) as u8;
37 let min = dt.minute().clamp(0, 59) as u8;
38 let sec = dt.second().clamp(0, 60) as u8;
39 let subsec_nanos = dt.nanosecond();
40 let attos = Dt::from_ns(subsec_nanos as i128, Scale::TAI).to_attos();
41
42 Dt::from_ymdhms_on(
43 yr,
44 mo,
45 day,
46 hr,
47 min,
48 sec,
49 clamp_i128_to_u64(attos),
50 Scale::UTC,
51 )
52 }
53
54 pub fn from_chrono_duration(dur: Duration) -> Self {
56 match dur.num_nanoseconds() {
57 Some(ns) => Self::from_ns(ns as i128, Scale::TAI),
58 None => {
59 let ns = if dur > Duration::zero() {
60 i64::MAX
61 } else {
62 i64::MIN
63 };
64 Self::from_ns(ns as i128, Scale::TAI)
65 }
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}