chrono_systemd_time/
local_datetime.rs1use std::ops::{Add, Sub};
2
3use chrono::LocalResult;
4use chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, TimeZone};
5
6use crate::Error;
7
8#[derive(Debug, PartialEq, Eq)]
12pub enum LocalDateTime<Tz: TimeZone> {
13 Single(DateTime<Tz>),
14 Ambiguous(DateTime<Tz>, DateTime<Tz>),
15}
16
17impl<Tz: TimeZone> TryFrom<LocalResult<DateTime<Tz>>> for LocalDateTime<Tz> {
18 type Error = Error;
19
20 fn try_from(res: LocalResult<DateTime<Tz>>) -> Result<Self, Self::Error> {
21 match res {
22 LocalResult::None => Err(Error::Never),
23 LocalResult::Single(dt) => Ok(LocalDateTime::Single(dt)),
24 LocalResult::Ambiguous(dt1, dt2) => Ok(LocalDateTime::Ambiguous(dt1, dt2)),
25 }
26 }
27}
28
29impl<Tz: TimeZone> LocalDateTime<Tz> {
30 pub fn single(self) -> Option<DateTime<Tz>> {
32 match self {
33 Self::Single(dt) => Some(dt),
34 _ => None,
35 }
36 }
37
38 pub fn earliest(self) -> DateTime<Tz> {
40 match self {
41 Self::Single(dt) | Self::Ambiguous(dt, _) => dt,
42 }
43 }
44
45 pub fn latest(self) -> DateTime<Tz> {
47 match self {
48 Self::Single(dt) | Self::Ambiguous(_, dt) => dt,
49 }
50 }
51}
52
53impl<Tz: TimeZone> LocalDateTime<Tz> {
54 pub(super) fn from_date(date: NaiveDate, tz: &Tz) -> Result<LocalDateTime<Tz>, Error> {
55 tz.from_local_datetime(&date.and_hms_opt(0, 0, 0).unwrap())
56 .try_into()
57 }
58
59 pub(super) fn from_datetime(
60 datetime: NaiveDateTime,
61 tz: &Tz,
62 ) -> Result<LocalDateTime<Tz>, Error> {
63 tz.from_local_datetime(&datetime).try_into()
64 }
65}
66
67impl<Tz: TimeZone> Add<Duration> for LocalDateTime<Tz> {
68 type Output = Self;
69
70 fn add(self, rhs: Duration) -> Self::Output {
71 match self {
72 Self::Single(dt) => Self::Single(dt + rhs),
73 Self::Ambiguous(dt1, dt2) => Self::Ambiguous(dt1 + rhs, dt2 + rhs),
74 }
75 }
76}
77
78impl<Tz: TimeZone> Sub<Duration> for LocalDateTime<Tz> {
79 type Output = Self;
80
81 fn sub(self, rhs: Duration) -> Self::Output {
82 match self {
83 Self::Single(dt) => Self::Single(dt - rhs),
84 Self::Ambiguous(dt1, dt2) => Self::Ambiguous(dt1 - rhs, dt2 - rhs),
85 }
86 }
87}