mybatis_drive/types/
timestamp_z.rs

1use std::alloc::Layout;
2use std::any::type_name;
3use std::ops::{Deref, DerefMut};
4use std::str::FromStr;
5use chrono::{NaiveDateTime, Utc};
6use rbson::Bson;
7use rbson::spec::BinarySubtype;
8use serde::{Deserializer, Serializer};
9use serde::de::Error;
10use sqlx_core::types::time;
11use crate::value::DateTimeNow;
12
13/// Rbatis Timestamp
14/// Rust type                Postgres type(s)
15/// time::OffsetDateTime      TIMESTAMPTZ
16#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
17pub struct TimestampZ {
18    pub inner: chrono::DateTime<Utc>,
19}
20
21impl From<chrono::DateTime<Utc>> for TimestampZ {
22    fn from(arg: chrono::DateTime<Utc>) -> Self {
23        Self {
24            inner: arg
25        }
26    }
27}
28
29impl From<&chrono::DateTime<Utc>> for TimestampZ {
30    fn from(arg: &chrono::DateTime<Utc>) -> Self {
31        Self {
32            inner: arg.clone()
33        }
34    }
35}
36
37impl serde::Serialize for TimestampZ {
38    #[inline]
39    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
40        use serde::ser::Error;
41        if type_name::<S::Error>().eq("rbson::ser::error::Error") {
42            return serializer.serialize_str(&format!("TimestampZ({})", self.inner.to_string()));
43        }else{
44            return self.inner.serialize(serializer);
45        }
46    }
47}
48
49impl<'de> serde::Deserialize<'de> for TimestampZ {
50    #[inline]
51    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
52        match Bson::deserialize(deserializer)? {
53            Bson::String(s) => {
54                if s.starts_with("TimestampZ(") && s.ends_with(")") {
55                    let inner_data = &s["TimestampZ(".len()..(s.len() - 1)];
56                    return Ok(Self {
57                        inner: {
58                            match chrono::DateTime::from_str(inner_data){
59                                Ok(v)=>{
60                                    Ok(v)
61                                }
62                                Err(e)=>{
63                                    log::error!("{}", e);
64                                    Err(D::Error::custom("parse TimestampZ fail"))
65                                }
66                            }
67                        }?,
68                    });
69                } else {
70                    return Ok(Self {
71                        inner:{
72                            match chrono::DateTime::from_str(&s){
73                                Ok(v)=>{
74                                    Ok(v)
75                                }
76                                Err(e)=>{
77                                    log::error!("{}", e);
78                                    Err(D::Error::custom("parse TimestampZ fail"))
79                                }
80                            }
81                        }?,
82                    });
83                }
84            }
85            _ => {
86                Err(D::Error::custom("deserialize un supported bson type!"))
87            }
88        }
89    }
90}
91
92impl TimestampZ {
93    pub fn as_timestamp(arg: &rbson::Timestamp) -> i64 {
94        let upper = (arg.time.to_le() as u64) << 32;
95        let lower = arg.increment.to_le() as u64;
96        (upper | lower) as i64
97    }
98
99    pub fn from_le_i64(val: i64) -> rbson::Timestamp {
100        let ts = val.to_le();
101        rbson::Timestamp {
102            time: ((ts as u64) >> 32) as u32,
103            increment: (ts & 0xFFFF_FFFF) as u32,
104        }
105    }
106}
107
108
109impl std::fmt::Display for TimestampZ {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        self.inner.fmt(f)
112    }
113}
114
115impl std::fmt::Debug for TimestampZ {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        self.inner.fmt(f)
118    }
119}
120
121impl Deref for TimestampZ {
122    type Target = chrono::DateTime<Utc>;
123
124    fn deref(&self) -> &Self::Target {
125        &self.inner
126    }
127}
128
129impl DerefMut for TimestampZ {
130    fn deref_mut(&mut self) -> &mut Self::Target {
131        &mut self.inner
132    }
133}
134
135impl TimestampZ {
136    pub fn now() -> Self {
137        Self {
138            inner: chrono::DateTime::from_utc(NaiveDateTime::now(),Utc)
139        }
140    }
141
142    pub fn now_utc() -> Self {
143        Self {
144            inner: chrono::DateTime::from_utc(NaiveDateTime::now(),Utc)
145        }
146    }
147
148    pub fn now_local() -> Self {
149        Self {
150            inner: chrono::DateTime::from_utc(NaiveDateTime::now(),Utc)
151        }
152    }
153
154    /// create from str
155    pub fn from_str(arg: &str) -> Result<Self, crate::error::Error> {
156        Ok(Self {
157            inner: chrono::DateTime::<Utc>::from_str(arg)?
158        })
159    }
160
161}
162
163#[cfg(test)]
164mod test {
165    use crate::types::TimestampZ;
166
167    #[test]
168    fn test_native() {
169        let dt = TimestampZ::now_utc();
170        let s = rbson::to_bson(&dt).unwrap();
171        let dt_new: TimestampZ = rbson::from_bson(s).unwrap();
172        println!("{},{}", dt.timestamp_millis(), dt_new.timestamp_millis());
173        assert_eq!(dt, dt_new);
174    }
175
176    #[test]
177    fn test_ser_de() {
178        let b = TimestampZ::now();
179        let bsons = rbson::to_bson(&b).unwrap();
180        let b_de: TimestampZ = rbson::from_bson(bsons).unwrap();
181        assert_eq!(b, b_de);
182    }
183
184    #[test]
185    fn test_str_de() {
186        let b = "2022-01-05 03:18:49 UTC".to_string();
187        let bsons = rbson::to_bson(&b).unwrap();
188        let b_de: TimestampZ = rbson::from_bson(bsons).unwrap();
189        //assert_eq!(b, b_de);
190    }
191}