serde_firestore_value/typ/
timestamp.rs

1/// Timestamp
2///
3/// `timestampValue` inner type.
4///
5/// <https://protobuf.dev/reference/protobuf/google.protobuf/#timestamp>
6/// <https://firebase.google.com/docs/firestore/reference/rest/Shared.Types/ArrayValue#Value>
7///
8/// # Examples
9///
10/// ```rust
11/// # fn test_timestamp() -> anyhow::Result<()> {
12/// #     use serde_firestore_value::google::firestore::v1::{value::ValueType, Value};
13/// #     use serde_firestore_value::{from_value, to_value, Timestamp};
14/// let o = Timestamp {
15///     seconds: 1_i64,
16///     nanos: 2_i32,
17/// };
18/// let v = Value {
19///     value_type: Some(ValueType::TimestampValue(prost_types::Timestamp {
20///         seconds: 1_i64,
21///         nanos: 2_i32,
22///     })),
23/// };
24/// let s = to_value(&o)?;
25/// let d = from_value::<'_, Timestamp>(&s)?;
26/// assert_eq!(s, v);
27/// assert_eq!(d, o);
28/// #     Ok(())
29/// # }
30/// ```
31#[derive(
32    Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
33)]
34#[serde(rename = "$__serde-firestore-value_private_timestamp")]
35pub struct Timestamp {
36    /// seconds
37    pub seconds: i64,
38    /// nanoseconds
39    pub nanos: i32,
40}
41
42impl Timestamp {
43    pub(crate) const NAME: &'static str = "$__serde-firestore-value_private_timestamp";
44}
45
46impl From<Timestamp> for prost_types::Timestamp {
47    fn from(Timestamp { seconds, nanos }: Timestamp) -> Self {
48        Self { seconds, nanos }
49    }
50}
51
52impl From<prost_types::Timestamp> for Timestamp {
53    fn from(prost_types::Timestamp { seconds, nanos }: prost_types::Timestamp) -> Self {
54        Self { seconds, nanos }
55    }
56}
57
58#[cfg(feature = "chrono")]
59impl std::convert::TryFrom<Timestamp> for chrono::DateTime<chrono::Utc> {
60    type Error = crate::Error;
61
62    fn try_from(Timestamp { seconds, nanos }: Timestamp) -> Result<Self, Self::Error> {
63        let nanos = u32::try_from(nanos).map_err(|_| {
64            crate::Error::from(crate::error::ErrorCode::Custom(format!(
65                "chrono::DateTime::<chrono::Utc>::try_from(Timestamp) / u32::try_from({})",
66                nanos
67            )))
68        })?;
69        Self::from_timestamp(seconds, nanos).ok_or_else(|| {
70            crate::Error::from(crate::error::ErrorCode::Custom(format!(
71                "chrono::DateTime::<chrono::Utc>::try_from(Timestamp) / chrono::DateTime::<chrono::Utc>::from_timestamp({}, {})",
72                seconds, nanos
73            )))
74        })
75    }
76}
77
78#[cfg(feature = "time")]
79impl std::convert::TryFrom<Timestamp> for time::OffsetDateTime {
80    type Error = crate::Error;
81
82    fn try_from(Timestamp { seconds, nanos }: Timestamp) -> Result<Self, Self::Error> {
83        let timestamp_nanos = i128::from(seconds) * 1_000_000_000_i128 + i128::from(nanos);
84        Self::from_unix_timestamp_nanos(timestamp_nanos).map_err(|e| {
85            crate::Error::from(crate::error::ErrorCode::Custom(format!(
86                "time::OffsetDateTime::try_from(Tiemstamp) / time::OffsetDateTime::from_unix_timestamp_nanos({}) : {}",
87                timestamp_nanos,
88                e
89            )))
90        })
91    }
92}
93
94#[cfg(feature = "chrono")]
95impl std::convert::TryFrom<chrono::DateTime<chrono::Utc>> for Timestamp {
96    type Error = crate::Error;
97
98    fn try_from(date_time: chrono::DateTime<chrono::Utc>) -> Result<Self, Self::Error> {
99        let seconds = date_time.timestamp();
100        let nanos = date_time.timestamp_subsec_nanos();
101        let nanos = i32::try_from(nanos).map_err(|_| {
102            crate::Error::from(crate::error::ErrorCode::Custom(format!(
103                "Timestamp::try_from(chrono::DateTime::<chrono::Utc>) / i32::try_from({})",
104                nanos
105            )))
106        })?;
107        Ok(Self { seconds, nanos })
108    }
109}
110
111#[cfg(feature = "time")]
112impl std::convert::TryFrom<time::OffsetDateTime> for Timestamp {
113    type Error = crate::Error;
114
115    fn try_from(offset_date_time: time::OffsetDateTime) -> Result<Self, Self::Error> {
116        let seconds = offset_date_time.unix_timestamp();
117        let nanos = offset_date_time.unix_timestamp_nanos() % 1_000_000_000_i128;
118        let nanos = i32::try_from(nanos).map_err(|_| {
119            crate::Error::from(crate::error::ErrorCode::Custom(format!(
120                "Timestamp::try_from(chrono::DateTime::<chrono::Utc>) / i32::try_from({})",
121                nanos
122            )))
123        })?;
124        Ok(Self { seconds, nanos })
125    }
126}