1use super::prelude::*;
4use chrono::{Datelike, Local, NaiveDateTime, TimeZone, Utc};
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Copy, PartialOrd, PartialEq, Serialize, Deserialize, Ord, Eq)]
9#[serde(transparent)]
10pub struct DateTime(chrono::DateTime<Utc>);
11
12impl std::fmt::Display for DateTime {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 write!(f, "{}", self.into_local().format("%a %b %d %Y, %H:%M"))
15 }
16}
17
18impl std::fmt::Debug for DateTime {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 write!(f, "{}", self.into_local())
21 }
22}
23
24impl DateTime {
25 pub fn now() -> Self {
27 DateTime(Utc::now())
28 }
29 pub fn year(&self) -> i32 {
31 self.0.year()
32 }
33 pub fn month(&self) -> u32 {
35 self.0.month()
36 }
37 pub fn day(&self) -> u32 {
39 self.0.day()
40 }
41 pub fn date(&self) -> Date {
43 Date(self.into_local().date())
44 }
45 pub fn into_local(&self) -> NaiveDateTime {
47 Local.from_utc_datetime(&self.0.naive_local()).naive_local()
48 }
49 pub fn from_local(local: &NaiveDateTime) -> Self {
51 let local = Local.from_local_datetime(local).unwrap();
52 Self(chrono::DateTime::from(local))
53 }
54 fn from_local_str(local: &str) -> Self {
56 Self(
57 Utc.from_local_datetime(
58 &Local
59 .datetime_from_str(local, "%Y-%m-%d %H:%M")
60 .unwrap()
61 .naive_utc(),
62 )
63 .unwrap(),
64 )
65 }
66 pub fn from_rfc3339(rfc3339: &str) -> Result<Self, Error> {
68 Ok(Self(
69 chrono::DateTime::parse_from_rfc3339(rfc3339)
70 .map_err(Error::DateTimeParse)?
71 .into(),
72 ))
73 }
74 pub fn format(&self, format: &str) -> String {
76 self.into_local().format(format).to_string()
77 }
78}
79
80impl From<chrono::DateTime<Utc>> for DateTime {
81 fn from(value: chrono::DateTime<Utc>) -> Self {
82 Self(value)
83 }
84}
85
86impl From<&str> for DateTime {
87 fn from(local: &str) -> Self {
88 Self::from_local_str(local)
89 }
90}
91
92impl From<DateTime> for chrono::DateTime<Utc> {
93 fn from(val: DateTime) -> Self {
94 val.0
95 }
96}
97
98impl From<DateTime> for chrono::DateTime<Local> {
99 fn from(val: DateTime) -> Self {
100 val.0.into()
101 }
102}
103
104impl std::ops::SubAssign<Duration> for DateTime {
105 fn sub_assign(&mut self, other: Duration) {
106 match other {
107 Duration::Zero => (),
108 Duration::HM { hours, minutes } => {
109 self.0 -= chrono::Duration::hours(hours) + chrono::Duration::minutes(minutes)
110 }
111 }
112 }
113}
114
115impl std::ops::AddAssign<Duration> for DateTime {
116 fn add_assign(&mut self, other: Duration) {
117 match other {
118 Duration::Zero => (),
119 Duration::HM { hours, minutes } => {
120 self.0 += chrono::Duration::hours(hours) + chrono::Duration::minutes(minutes)
121 }
122 }
123 }
124}
125
126impl std::ops::Add<Duration> for DateTime {
127 type Output = DateTime;
128 fn add(self, other: Duration) -> Self::Output {
129 match other {
130 Duration::Zero => self,
131 Duration::HM { hours, minutes } => {
132 Self(self.0 + chrono::Duration::hours(hours) + chrono::Duration::minutes(minutes))
133 }
134 }
135 }
136}
137
138impl std::ops::Sub<Duration> for DateTime {
139 type Output = DateTime;
140 fn sub(self, other: Duration) -> Self::Output {
141 match other {
142 Duration::Zero => self,
143 Duration::HM { hours, minutes } => {
144 Self(self.0 - chrono::Duration::hours(hours) - chrono::Duration::minutes(minutes))
145 }
146 }
147 }
148}
149
150impl std::ops::Add<chrono::Duration> for DateTime {
151 type Output = DateTime;
152 fn add(self, other: chrono::Duration) -> Self::Output {
153 Self(self.0 + other)
154 }
155}
156
157impl std::ops::Sub<chrono::Duration> for DateTime {
158 type Output = DateTime;
159 fn sub(self, other: chrono::Duration) -> Self::Output {
160 Self(self.0 - other)
161 }
162}
163
164impl std::ops::Sub for &DateTime {
165 type Output = Duration;
166 fn sub(self, other: &DateTime) -> Self::Output {
167 let minutes = (self.0 - other.0).num_minutes();
168 Duration::HM {
169 hours: minutes / 60,
170 minutes: minutes % 60,
171 }
172 }
173}
174
175#[derive(Debug, PartialEq, Clone, PartialOrd, Ord, Eq)]
177pub struct Date(chrono::NaiveDate);
178
179impl Date {
180 pub fn first_day_of_month(&self) -> DateTime {
181 DateTime::from_local(
182 &chrono::NaiveDate::from_ymd_opt(self.0.year(), self.0.month(), 1)
183 .unwrap()
184 .and_hms_opt(0, 0, 0)
185 .unwrap(),
186 )
187 }
188 pub fn first_day_of_previous_month(&self) -> DateTime {
189 DateTime::from_local(
190 &chrono::NaiveDate::from_ymd_opt(self.0.year(), self.0.month() - 1, 1)
191 .unwrap()
192 .and_hms_opt(0, 0, 0)
193 .unwrap(),
194 )
195 }
196}
197
198impl From<DateTime> for Date {
199 fn from(value: DateTime) -> Self {
200 let datetime: chrono::DateTime<Utc> = value.into();
201 Date(datetime.date_naive())
202 }
203}
204
205impl std::fmt::Display for Date {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(f, "{}", self.0)
208 }
209}