Skip to main content

date_differencer/add_diff/
chrono_support.rs

1use chrono::{DateTime, Duration, LocalResult, NaiveDate, NaiveDateTime, TimeZone};
2
3use super::{AddDateTimeDiff, AddedDateTimeParts, DateTimeDiff, add_date_time_parts};
4
5#[inline]
6fn naive_date_time_from_parts(parts: AddedDateTimeParts) -> Option<NaiveDateTime> {
7    NaiveDate::from_ymd_opt(parts.year, parts.month as u32, parts.day as u32)?.and_hms_nano_opt(
8        parts.hour as u32,
9        parts.minute as u32,
10        parts.second as u32,
11        parts.nanosecond,
12    )
13}
14
15impl AddDateTimeDiff for NaiveDateTime {
16    type Output = Option<NaiveDateTime>;
17
18    #[inline]
19    fn add_date_time_diff(self, date_time_diff: &impl DateTimeDiff) -> Self::Output {
20        let parts = add_date_time_parts(&self, date_time_diff)?;
21
22        naive_date_time_from_parts(parts)
23    }
24}
25
26impl<Tz> AddDateTimeDiff for DateTime<Tz>
27where
28    Tz: TimeZone,
29    DateTime<Tz>: Ord,
30{
31    type Output = LocalResult<DateTime<Tz>>;
32
33    #[inline]
34    fn add_date_time_diff(self, date_time_diff: &impl DateTimeDiff) -> Self::Output {
35        let parts = match add_date_time_parts(&self, date_time_diff) {
36            Some(parts) => parts,
37            None => return LocalResult::None,
38        };
39
40        match self.timezone().with_ymd_and_hms(
41            parts.year,
42            parts.month as u32,
43            parts.day as u32,
44            parts.hour as u32,
45            parts.minute as u32,
46            parts.second as u32,
47        ) {
48            LocalResult::Single(v) => {
49                match v.checked_add_signed(Duration::nanoseconds(parts.nanosecond as i64)) {
50                    Some(v) => LocalResult::Single(v),
51                    None => LocalResult::None,
52                }
53            },
54            LocalResult::Ambiguous(a, b) => {
55                let delta = Duration::nanoseconds(parts.nanosecond as i64);
56                LocalResult::Ambiguous(
57                    match a.checked_add_signed(delta) {
58                        Some(v) => v,
59                        None => return LocalResult::None,
60                    },
61                    match b.checked_add_signed(delta) {
62                        Some(v) => v,
63                        None => return LocalResult::None,
64                    },
65                )
66            },
67            LocalResult::None => LocalResult::None,
68        }
69    }
70}