date_differencer/add_diff/
chrono_support.rs1use 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}