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