From 93a1481305557c2101c64928bc208bde744409f1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 29 Nov 2022 00:39:49 +0100 Subject: [PATCH] Less verbose cache age formatting (#849) Previously the cache age was formatted with nanosecond resolution, which is too fine-grained even for Rustaceans. Now the format is limited to days, hours, minutes, and seconds. With that, the cache age becomes more easily parseable by humans. --- lychee-bin/src/formatters/duration.rs | 74 +++++++++++++++++++++++++++ lychee-bin/src/formatters/mod.rs | 1 + lychee-bin/src/main.rs | 9 ++-- 3 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 lychee-bin/src/formatters/duration.rs diff --git a/lychee-bin/src/formatters/duration.rs b/lychee-bin/src/formatters/duration.rs new file mode 100644 index 0000000..4cf4bcb --- /dev/null +++ b/lychee-bin/src/formatters/duration.rs @@ -0,0 +1,74 @@ +use std::fmt; + +/// Wrapper struct around `elapsed.as_secs()` for custom formatting. +/// +/// # Examples +/// +/// ``` +/// use lychee_bin::formatters::Duration; +/// +/// let duration = Duration::from_secs(1); +/// assert_eq!(duration.to_string(), "1s"); +/// +/// let duration = Duration::from_secs(60); +/// assert_eq!(duration.to_string(), "1m"); +/// +/// let duration = Duration::from_secs(61); +/// assert_eq!(duration.to_string(), "1m 1s"); +/// +/// let duration = Duration::from_secs(3661); +/// assert_eq!(duration.to_string(), "1h 1m 1s"); +/// ``` +pub(crate) struct Duration { + elapsed: u64, +} + +impl Duration { + /// Create a new `Duration` from the given number of seconds. + pub(crate) const fn from_secs(elapsed: u64) -> Self { + Self { elapsed } + } +} + +impl fmt::Display for Duration { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let days = self.elapsed / 86400; + let hours = (self.elapsed % 86400) / 3600; + let minutes = (self.elapsed % 3600) / 60; + let seconds = self.elapsed % 60; + + if days > 0 { + write!(f, "{}d {}h {}m {}s", days, hours, minutes, seconds) + } else if hours > 0 { + write!(f, "{}h {}m {}s", hours, minutes, seconds) + } else if minutes > 0 { + write!(f, "{}m {}s", minutes, seconds) + } else { + write!(f, "{}s", seconds) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_formatting() { + let duration = Duration::from_secs(61); + assert_eq!(duration.to_string(), "1m 1s"); + + let duration = Duration::from_secs(3661); + assert_eq!(duration.to_string(), "1h 1m 1s"); + + let duration = Duration::from_secs(90061); + assert_eq!(duration.to_string(), "1d 1h 1m 1s"); + + let duration = Duration::from_secs(0); + assert_eq!(duration.to_string(), "0s"); + + // 100 years printed as days + let duration = Duration::from_secs(3_153_600_000); + assert_eq!(duration.to_string(), "36500d 0h 0m 0s"); + } +} diff --git a/lychee-bin/src/formatters/mod.rs b/lychee-bin/src/formatters/mod.rs index 0a391c1..1738112 100644 --- a/lychee-bin/src/formatters/mod.rs +++ b/lychee-bin/src/formatters/mod.rs @@ -1,3 +1,4 @@ +pub(crate) mod duration; pub(crate) mod response; pub(crate) mod stats; diff --git a/lychee-bin/src/main.rs b/lychee-bin/src/main.rs index ab97ffb..9a6f9f4 100644 --- a/lychee-bin/src/main.rs +++ b/lychee-bin/src/main.rs @@ -85,6 +85,7 @@ mod stats; mod time; mod verbosity; +use crate::formatters::duration::Duration; use crate::{ cache::{Cache, StoreExt}, color::color, @@ -191,15 +192,15 @@ fn load_cache(cfg: &Config) -> Option { if elapsed > cfg.max_cache_age { warn!( "Cache is too old (age: {}, max age: {}). Discarding and recreating.", - humantime::format_duration(elapsed), - humantime::format_duration(cfg.max_cache_age) + Duration::from_secs(elapsed.as_secs()), + Duration::from_secs(cfg.max_cache_age.as_secs()) ); return None; } info!( "Cache is recent (age: {}, max age: {}). Using.", - humantime::format_duration(elapsed), - humantime::format_duration(cfg.max_cache_age) + Duration::from_secs(elapsed.as_secs()), + Duration::from_secs(cfg.max_cache_age.as_secs()) ); } }