From 321ab1889046911a5e26722bd5f2ddc6b984866f Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Thu, 25 Sep 2025 20:20:48 +0300 Subject: [PATCH] add `HumanDuration` --- Cargo.toml | 1 + src/time/duration.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ src/time/mod.rs | 3 +++ 3 files changed, 61 insertions(+) create mode 100644 src/time/duration.rs diff --git a/Cargo.toml b/Cargo.toml index a6afb09..3d7d4da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,3 +59,4 @@ color-eyre = { version = "0.6.5", optional = true } eyre = { version = "0.6.12" } num_cpus = { version = "1.17.0", optional = true } either = "1.15.0" +humantime = "2.3.0" diff --git a/src/time/duration.rs b/src/time/duration.rs new file mode 100644 index 0000000..3bf49d9 --- /dev/null +++ b/src/time/duration.rs @@ -0,0 +1,57 @@ +use std::{borrow::Cow, ops::Deref, time::Duration}; + +use compact_str::{CompactString, ToCompactString}; + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::data; + +#[repr(transparent)] +#[data(crate = crate, copy, not(serde, schemars))] +pub struct HumanDuration(pub Duration); + +impl Deref for HumanDuration { + type Target = Duration; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl JsonSchema for HumanDuration { + fn schema_name() -> Cow<'static, str> { + Cow::Borrowed("HumanDuration") + } + + fn schema_id() -> Cow<'static, str> { + Cow::Borrowed(concat!(module_path!(), "::HumanDuration")) + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + String::json_schema(generator) + } +} + +impl<'de> Deserialize<'de> for HumanDuration { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = CompactString::deserialize(deserializer)?; + humantime::parse_duration(&s) + .map_err(|e| serde::de::Error::custom(e)) + .map(Self) + } +} + +impl Serialize for HumanDuration { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + humantime::format_duration(self.0) + .to_compact_string() + .serialize(serializer) + } +} diff --git a/src/time/mod.rs b/src/time/mod.rs index 65d6408..d7d0e0b 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -30,6 +30,7 @@ pub use self::{ clock::{Clock, Mock, RealTime}, date::{Date, Day, Leapness, LooseDate, Month, Year}, + duration::HumanDuration, time::{Hours, Mins, PreciseTime, Secs, SecsTime, SubsecNanos, Time}, timestamp::Timestamp, }; @@ -38,6 +39,8 @@ pub mod ser; pub mod str; pub mod tz; +mod duration; + mod clock; mod date; mod time;