diff options
author | Harald Eilertsen <haraldei@anduin.net> | 2024-01-13 13:00:25 +0100 |
---|---|---|
committer | Harald Eilertsen <haraldei@anduin.net> | 2024-01-13 13:00:25 +0100 |
commit | d9fa0a00889e40baf5289a65e17d47727b7c506e (patch) | |
tree | 7701c959a0351f381e06fa287f5f1b525f889485 /src/stream | |
parent | a43422b4d4ed4d89e1ca8fc316dd372e5dd9cb34 (diff) | |
download | rust-zotapi-d9fa0a00889e40baf5289a65e17d47727b7c506e.tar.gz rust-zotapi-d9fa0a00889e40baf5289a65e17d47727b7c506e.tar.bz2 rust-zotapi-d9fa0a00889e40baf5289a65e17d47727b7c506e.zip |
Add stream::DateTime struct
As the date and time returned in the json data from the zot stream api's
neither contains any timezone information, nor follow the RFC3339 format
expected by Chrono, we need to make our own date time type, and handle
deserialization ourselves.
Diffstat (limited to 'src/stream')
-rw-r--r-- | src/stream/datetime.rs | 93 | ||||
-rw-r--r-- | src/stream/streamitem.rs | 11 |
2 files changed, 104 insertions, 0 deletions
diff --git a/src/stream/datetime.rs b/src/stream/datetime.rs new file mode 100644 index 0000000..8b67e78 --- /dev/null +++ b/src/stream/datetime.rs @@ -0,0 +1,93 @@ +/** + * Date and time representation in the stream. + * + * SPDX-FileCopyrightText: 2023 Eilertsens Kodeknekkeri + * SPDX-FileCopyrightText: 2023 Harald Eilertsen <haraldei@anduin.net> + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use chrono::NaiveDateTime; +use serde::Deserialize; + +/** + * Handle date and time. + * + * This is mainly a wrapper around the chrono::NaiveDateTime struct, + * as the date and time returned by the json data from the zot stream + * API's does not contain any timezone information. + */ +#[derive(Debug, PartialEq)] +pub struct DateTime { + datetime: Option<NaiveDateTime> +} + +/* + * Implement Display for the DateTime type, so that it will display + * using the correct time and date format by default. + */ +impl std::fmt::Display for DateTime { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.datetime { + Some(dt) => write!(f, "{}", dt.format("%Y-%m-%d %H:%M:%S")), + None => write!(f, "0000-00-00 00:00:00"), + } + } +} + +/* + * Since the date and time format returned in the json from the + * stream API, does not conform to the RFC3339 format expected by + * the default chrono deserializer, we have to implement our own + * deserializer. + */ +impl<'de> Deserialize<'de> for DateTime { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::de::Deserializer<'de>, + { + Ok(deserializer.deserialize_str(DateTimeVisitor)?) + } +} + +struct DateTimeVisitor; + +impl<'de> serde::de::Visitor<'de> for DateTimeVisitor { + type Value = DateTime; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a date and time formatted string") + } + + fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + let datetime = if s == "0000-00-00 00:00:00" { + None + } else { + Some(NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") + .map_err(|_| E::custom(format!("invalid date time format: {}", s)))?) + }; + + Ok(Self::Value{ datetime }) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_deserialize_datetime() { + let tests = vec![ + r#""0000-00-00 00:00:00""#, + r#""2016-12-17 13:37:00""#, + ]; + + for test in tests { + let datetime: DateTime = serde_json::from_str(test).unwrap(); + assert_eq!(test.trim_matches('"'), datetime.to_string()); + } + } +} diff --git a/src/stream/streamitem.rs b/src/stream/streamitem.rs index 1934dfe..514cae3 100644 --- a/src/stream/streamitem.rs +++ b/src/stream/streamitem.rs @@ -7,6 +7,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +use super::datetime::DateTime; use super::verb::Verb; use serde::Deserialize; @@ -32,6 +33,16 @@ pub struct StreamItem { pub item_type: StreamItemType, pub encoding: StreamItemEncoding, + /* + * Date and time fields for when the item was + * created, last edited or commented, as well as + * when/if it expires. + */ + pub created: DateTime, + pub edited: DateTime, + pub expires: DateTime, + pub commented: DateTime, + pub verb: Verb, pub title: String, |