backend/
autosurgeon_datetime.rs

1use autosurgeon::HydrateError;
2use chrono::{DateTime, TimeZone, Utc};
3
4fn millis_to_datetime(millis: i64) -> Result<DateTime<Utc>, HydrateError> {
5    Utc.timestamp_millis_opt(millis).single().ok_or_else(|| {
6        HydrateError::unexpected("valid timestamp", "invalid timestamp millis".to_string())
7    })
8}
9
10/// Autosurgeon serialization of `DateTime<Utc>` as milliseconds since Unix epoch.
11pub mod datetime_millis {
12    use autosurgeon::{HydrateError, ReadDoc, Reconcile, Reconciler};
13    use chrono::{DateTime, Utc};
14
15    /// Reconciles a `DateTime<Utc>` as milliseconds since Unix epoch.
16    pub fn reconcile<R: Reconciler>(dt: &DateTime<Utc>, reconciler: R) -> Result<(), R::Error> {
17        dt.timestamp_millis().reconcile(reconciler)
18    }
19
20    /// Hydrates a `DateTime<Utc>` from milliseconds since Unix epoch.
21    pub fn hydrate<D: ReadDoc>(
22        doc: &D,
23        obj: &automerge::ObjId,
24        prop: autosurgeon::Prop<'_>,
25    ) -> Result<DateTime<Utc>, HydrateError> {
26        let millis: i64 = autosurgeon::hydrate_prop(doc, obj, prop)?;
27        super::millis_to_datetime(millis)
28    }
29}
30
31/// Autosurgeon serialization of `Option<DateTime<Utc>>` as optional milliseconds since Unix epoch.
32pub mod option_datetime_millis {
33    use autosurgeon::{HydrateError, ReadDoc, Reconcile, Reconciler};
34    use chrono::{DateTime, Utc};
35
36    /// Reconciles an `Option<DateTime<Utc>>` as optional milliseconds since Unix epoch.
37    pub fn reconcile<R: Reconciler>(
38        dt: &Option<DateTime<Utc>>,
39        reconciler: R,
40    ) -> Result<(), R::Error> {
41        match dt {
42            Some(dt) => super::datetime_millis::reconcile(dt, reconciler),
43            None => None::<i64>.reconcile(reconciler),
44        }
45    }
46
47    /// Hydrates an `Option<DateTime<Utc>>` from optional milliseconds since Unix epoch.
48    pub fn hydrate<D: ReadDoc>(
49        doc: &D,
50        obj: &automerge::ObjId,
51        prop: autosurgeon::Prop<'_>,
52    ) -> Result<Option<DateTime<Utc>>, HydrateError> {
53        let millis: Option<i64> = autosurgeon::hydrate_prop(doc, obj, prop)?;
54        millis.map(super::millis_to_datetime).transpose()
55    }
56}