1use ::chrono::prelude::*;
2
3#[cfg(feature = "sea-orm")]
4pub use ::sea_orm::prelude::DateTimeUtc;
5#[cfg(not(feature = "sea-orm"))]
6pub type DateTimeUtc = DateTime<Utc>;
7
8pub type UnixTimeMicros = i64;
10
11pub type DurationMicros = i64;
13
14pub trait UnixTimestampXlf: Sized {
15 fn micros_from_days(&self) -> Self;
17
18 fn micros_from_hours(&self) -> Self;
20
21 fn micros_from_mins(&self) -> Self;
23
24 fn micros_from_secs(&self) -> Self;
26
27 fn micros_from_secs_f64(secs: f64) -> Self;
29
30 fn micros_from_millis(&self) -> Self;
32
33 fn micros_as_unix_timestamp(&self) -> DateTimeUtc;
35
36 fn micros_as_unix_timestamp_opt(&self) -> chrono::LocalResult<DateTimeUtc>;
38
39 fn micros_now() -> Self;
41
42 fn micros_from_utc_str(s: impl AsRef<str>) -> Option<Self>;
44
45 fn micros_into_utc_str(&self) -> String;
47}
48
49#[inline]
51pub fn utc_default() -> DateTimeUtc {
52 Utc.timestamp_opt(0, 0).unwrap()
53}
54
55pub fn utc_from_str(s: &str) -> chrono::ParseResult<DateTimeUtc> {
57 DateTime::parse_from_rfc3339(s).map(DateTime::<Utc>::from)
58}
59
60pub fn utc_into_str(utc: DateTimeUtc) -> String {
63 let n = utc.naive_local();
64 format!(
65 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:06}Z",
66 n.year(),
67 n.month(),
68 n.day(),
69 n.hour(),
70 n.minute(),
71 n.second(),
72 n.nanosecond() / 1000
73 )
74}
75
76impl UnixTimestampXlf for UnixTimeMicros {
77 #[inline]
78 fn micros_from_days(&self) -> Self {
79 self * (24 * 60 * 60 * 1_000_000)
80 }
81
82 #[inline]
83 fn micros_from_hours(&self) -> Self {
84 self * (60 * 60 * 1_000_000)
85 }
86
87 #[inline]
88 fn micros_from_mins(&self) -> Self {
89 self * (60 * 1_000_000)
90 }
91
92 #[inline]
93 fn micros_from_secs(&self) -> Self {
94 self * 1_000_000
95 }
96
97 #[inline]
98 fn micros_from_secs_f64(secs: f64) -> Self {
99 (secs * 1_000_000.0) as Self
100 }
101
102 fn micros_from_millis(&self) -> Self {
103 self * 1_000
104 }
105
106 fn micros_as_unix_timestamp(&self) -> DateTimeUtc {
107 self.micros_as_unix_timestamp_opt()
108 .single()
109 .unwrap_or_else(utc_default)
110 }
111
112 fn micros_as_unix_timestamp_opt(&self) -> chrono::LocalResult<DateTimeUtc> {
113 let (mut secs, mut micros) = (self / 1_000_000, self % 1_000_000);
114 if micros < 0 {
115 secs -= 1;
116 micros += 1_000_000;
117 }
118 Utc.timestamp_opt(secs, micros as u32 * 1_000)
119 }
120
121 fn micros_now() -> Self {
122 Utc::now().timestamp_micros()
123 }
124
125 fn micros_from_utc_str(s: impl AsRef<str>) -> Option<Self> {
126 let s = s.as_ref();
127 s.parse::<UnixTimeMicros>().ok().or_else(|| {
128 DateTime::parse_from_rfc3339(s)
129 .ok()
130 .map(|x| DateTime::<Utc>::from(x).timestamp_micros())
131 })
132 }
133
134 fn micros_into_utc_str(&self) -> String {
135 utc_into_str(self.micros_as_unix_timestamp())
136 }
137}
138
139#[cfg(feature = "serde")]
143pub mod serde_x_utc {
144 use super::*;
145 use ::serde::{
146 de::{self, Unexpected},
147 ser::Serializer,
148 };
149 use ::std::fmt;
150
151 struct DeUtcVisitor;
152
153 impl<'de> de::Visitor<'de> for DeUtcVisitor {
154 type Value = DateTime<Utc>;
155
156 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
157 write!(formatter, "a formatted date and time string")
158 }
159
160 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
162 where
163 E: de::Error,
164 {
165 match Utc.timestamp_millis_opt(value as i64).single() {
166 Some(v) => Ok(v),
167 _ => Err(de::Error::invalid_type(Unexpected::Unsigned(value), &self)),
168 }
169 }
170
171 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
173 where
174 E: de::Error,
175 {
176 match Utc.timestamp_millis_opt(value).single() {
177 Some(v) => Ok(v),
178 _ => Err(de::Error::invalid_type(Unexpected::Signed(value), &self)),
179 }
180 }
181
182 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
184 where
185 E: de::Error,
186 {
187 let secs = value.floor();
188 match Utc
189 .timestamp_opt(secs as i64, ((value - secs) * 1000000000.) as u32)
190 .single()
191 {
192 Some(v) => Ok(v),
193 _ => Err(de::Error::invalid_type(Unexpected::Float(value), &self)),
194 }
195 }
196
197 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
198 where
199 E: de::Error,
200 {
201 match DateTime::parse_from_rfc3339(value) {
202 Ok(v) => Ok(DateTime::<Utc>::from(v)),
203 _ => Err(de::Error::invalid_type(Unexpected::Str(value), &self)),
204 }
205 }
206 }
207
208 struct DeUtcMicrosVisitor;
209
210 impl<'de> de::Visitor<'de> for DeUtcMicrosVisitor {
211 type Value = UnixTimeMicros;
212
213 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
214 write!(formatter, "a formatted date and time string")
215 }
216
217 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
219 where
220 E: de::Error,
221 {
222 UnixTimeMicros::try_from(value)
223 .map_err(|_| de::Error::invalid_type(Unexpected::Unsigned(value), &self))
224 }
225
226 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
228 where
229 E: de::Error,
230 {
231 Ok(value)
232 }
233
234 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
236 where
237 E: de::Error,
238 {
239 Ok(value as i64)
240 }
241
242 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
243 where
244 E: de::Error,
245 {
246 match DateTime::parse_from_rfc3339(value) {
247 Ok(v) => Ok(DateTime::<Utc>::from(v).timestamp_micros()),
248 _ => Err(de::Error::invalid_type(Unexpected::Str(value), &self)),
249 }
250 }
251 }
252
253 pub fn serialize<S>(utc: &DateTimeUtc, serializer: S) -> Result<S::Ok, S::Error>
255 where
256 S: Serializer,
257 {
258 serializer.serialize_str(&utc_into_str(*utc))
259 }
260
261 pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTimeUtc, D::Error>
263 where
264 D: de::Deserializer<'de>,
265 {
266 deserializer.deserialize_any(DeUtcVisitor)
267 }
268
269 pub mod f64 {
270 use super::*;
271
272 pub fn serialize<S>(utc: &DateTimeUtc, serializer: S) -> Result<S::Ok, S::Error>
274 where
275 S: Serializer,
276 {
277 serializer.serialize_f64(utc.timestamp_micros() as f64 / 1000000.)
278 }
279
280 pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTimeUtc, D::Error>
282 where
283 D: de::Deserializer<'de>,
284 {
285 deserializer.deserialize_f64(DeUtcVisitor)
286 }
287 }
288
289 pub mod micros {
290 use super::*;
291
292 pub fn serialize<S>(micros: UnixTimeMicros, serializer: S) -> Result<S::Ok, S::Error>
294 where
295 S: Serializer,
296 {
297 serializer.serialize_i64(micros)
298 }
299
300 pub fn deserialize<'de, D>(deserializer: D) -> Result<UnixTimeMicros, D::Error>
302 where
303 D: de::Deserializer<'de>,
304 {
305 deserializer.deserialize_i64(DeUtcMicrosVisitor)
306 }
307 }
308}
309
310#[cfg(feature = "serde")]
311pub use serde_x_utc::{deserialize as de_x_utc, serialize as ser_x_utc};
312#[cfg(feature = "serde")]
313pub use serde_x_utc::{f64::deserialize as de_x_utc_f64, f64::serialize as ser_x_utc_f64};
314#[cfg(feature = "serde")]
315pub use serde_x_utc::{
316 micros::deserialize as de_x_utc_micros, micros::serialize as ser_x_utc_micros,
317};
318
319#[cfg(test)]
322mod tests {
323 #[cfg(feature = "serde")]
324 #[test]
325 fn test_utc_default() {
326 use super::*;
327 use crate::prelude::*;
328
329 #[derive(Clone, Debug, SmartDefault, Serialize, Deserialize)]
330 struct Person {
331 #[serde(default)]
332 name: String,
333 year: i32,
334 optional: Option<i32>,
335 #[serde(default = "utc_default")]
337 #[default(utc_default())]
338 birth_on: DateTime<Utc>,
339 }
340
341 let jsn = json!({
342 "year": 32,
343 "birth_on": utc_into_str(Utc::now()),
344 });
345 let a: Person = serde_json::from_value(jsn).unwrap();
346 println!("{:?}", &a);
347
348 let s = serde_json::to_string(&a).unwrap();
349 println!("{}", &s);
350
351 let utc = utc_from_str("2022-01-01T00:00:01.345677Z").unwrap();
352 assert_eq!(
353 UnixTimeMicros::micros_from_utc_str("2022-01-01T00:00:01.345677Z"),
354 Some(utc.timestamp_micros())
355 );
356 assert_eq!(
357 UnixTimeMicros::micros_from_utc_str(utc.timestamp_micros().to_string()),
358 Some(utc.timestamp_micros())
359 );
360 }
361}