aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Eilertsen <haraldei@anduin.net>2024-01-13 13:00:25 +0100
committerHarald Eilertsen <haraldei@anduin.net>2024-01-13 13:00:25 +0100
commitd9fa0a00889e40baf5289a65e17d47727b7c506e (patch)
tree7701c959a0351f381e06fa287f5f1b525f889485
parenta43422b4d4ed4d89e1ca8fc316dd372e5dd9cb34 (diff)
downloadrust-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.
-rw-r--r--Cargo.toml1
-rw-r--r--src/stream.rs2
-rw-r--r--src/stream/datetime.rs93
-rw-r--r--src/stream/streamitem.rs11
4 files changed, 107 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index a271637..4b76f68 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ authors = ["haraldei"]
edition = "2021"
[dependencies]
+chrono = "0.4.0"
clap = "2.33.0"
dotenv = "0.15"
reqwest = { version = "0.11", features = ["default-tls", "multipart"] }
diff --git a/src/stream.rs b/src/stream.rs
index 438ef0f..0348822 100644
--- a/src/stream.rs
+++ b/src/stream.rs
@@ -11,9 +11,11 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+mod datetime;
mod streamitem;
mod verb;
+pub use datetime::DateTime;
pub use streamitem::{
StreamItem,
StreamItemEncoding,
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,