mybatis_drive/types/
timestamp.rs

1use std::alloc::Layout;
2use std::ops::{Deref, DerefMut};
3use rbson::Bson;
4use serde::{Deserializer, Serializer};
5use serde::de::Error;
6use sqlx_core::types::time;
7
8/// Rbatis Timestamp
9/// Rust type                Postgres type(s)
10/// time::PrimitiveDateTime   TIMESTAMP
11/// time::OffsetDateTime      TIMESTAMPTZ
12///
13/// Rust type                 MySQL type(s)
14/// time::OffsetDateTime      TIMESTAMP
15#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub struct Timestamp {
17    pub inner: time::OffsetDateTime,
18}
19
20impl From<time::OffsetDateTime> for Timestamp {
21    fn from(arg: time::OffsetDateTime) -> Self {
22        Self {
23            inner: arg
24        }
25    }
26}
27
28impl From<&time::OffsetDateTime> for Timestamp {
29    fn from(arg: &time::OffsetDateTime) -> Self {
30        Self {
31            inner: arg.clone()
32        }
33    }
34}
35
36impl serde::Serialize for Timestamp {
37    #[inline]
38    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
39        let bs = Timestamp::from_le_i64(self.inner.unix_timestamp());
40        return bs.serialize(serializer);
41    }
42}
43
44impl<'de> serde::Deserialize<'de> for Timestamp {
45    #[inline]
46    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
47        match Bson::deserialize(deserializer)? {
48            Bson::String(s) => {
49                return Ok(Self {
50                    inner: time::OffsetDateTime::parse(&s, "%F %T %z").or_else(|e| Err(D::Error::custom(e.to_string())))?,
51                });
52            }
53            Bson::Int64(data) => {
54                return Ok(Timestamp::from_unix_timestamp(data));
55            }
56            Bson::Timestamp(data) => {
57                return Ok(Timestamp::from(data));
58            }
59            _ => {
60                Err(D::Error::custom("deserialize un supported bson type!"))
61            }
62        }
63    }
64}
65
66impl Timestamp {
67    pub fn as_timestamp(arg: &rbson::Timestamp) -> i64 {
68        let upper = (arg.time.to_le() as u64) << 32;
69        let lower = arg.increment.to_le() as u64;
70        (upper | lower) as i64
71    }
72
73    pub fn from_le_i64(val: i64) -> rbson::Timestamp {
74        let ts = val.to_le();
75        rbson::Timestamp {
76            time: ((ts as u64) >> 32) as u32,
77            increment: (ts & 0xFFFF_FFFF) as u32,
78        }
79    }
80}
81
82impl From<rbson::Timestamp> for Timestamp {
83    fn from(data: rbson::Timestamp) -> Self {
84        let offset = time::OffsetDateTime::from_unix_timestamp(Timestamp::as_timestamp(&data));
85        Self {
86            inner: offset
87        }
88    }
89}
90
91impl std::fmt::Display for Timestamp {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        self.inner.fmt(f)
94    }
95}
96
97impl std::fmt::Debug for Timestamp {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        self.inner.fmt(f)
100    }
101}
102
103impl Deref for Timestamp {
104    type Target = time::OffsetDateTime;
105
106    fn deref(&self) -> &Self::Target {
107        &self.inner
108    }
109}
110
111impl DerefMut for Timestamp {
112    fn deref_mut(&mut self) -> &mut Self::Target {
113        &mut self.inner
114    }
115}
116
117impl Timestamp {
118    // pub fn now() -> Self {
119    //     let offset_date_time = time::OffsetDateTime::try_now_local().unwrap();
120
121    //     Self {
122    //         inner: time::OffsetDateTime::from_unix_timestamp(offset_date_time.unix_timestamp())
123    //     }
124    // }
125
126    /// create from str
127    pub fn from_str(arg: &str) -> Result<Self, crate::error::Error> {
128        let inner = time::OffsetDateTime::parse(arg, "%F %T %z")?;
129        Ok(Self {
130            inner: inner
131        })
132    }
133
134    pub fn timestamp_millis(&self) -> i64 {
135        self.inner.unix_timestamp()
136    }
137
138    pub fn from_unix_timestamp(arg: i64) -> Self {
139        Self {
140            inner: time::OffsetDateTime::from_unix_timestamp(arg)
141        }
142    }
143}
144
145
146#[cfg(test)]
147mod test {
148    use super::*;
149
150    // #[test]
151    // fn test_ser_de() {
152    //     let b = Timestamp::now();
153    //     let bsons = rbson::to_bson(&b).unwrap();
154    //     let b_de: Timestamp = rbson::from_bson(bsons).unwrap();
155    //     assert_eq!(b, b_de);
156    // }
157}