#![allow(clippy::enum_glob_use)] use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[inline] #[must_use] #[allow(clippy::as_conversions)] pub fn now_millis() -> u64 { UNIX_EPOCH .elapsed() .expect("positive duration after epoch") .as_millis() as u64 } #[must_use] pub fn rfc2822_from_seconds(epoch: i64) -> String { use chrono::{DateTime, Utc}; DateTime::::from_timestamp(epoch, 0) .unwrap_or_default() .to_rfc2822() } #[must_use] pub fn format(ts: SystemTime, str: &str) -> String { use chrono::{DateTime, Utc}; let dt: DateTime = ts.into(); dt.format(str).to_string() } #[must_use] pub fn pretty(d: Duration) -> String { use Unit::*; let fmt = |w, f, u| format!("{w}.{f} {u}"); let gen64 = |w, f, u| fmt(w, (f * 100.0) as u64, u); let gen128 = |w, f, u| gen64(u64::try_from(w).expect("u128 to u64"), f, u); match whole_and_frac(d) { (Days(whole), frac) => gen64(whole, frac, "days"), (Hours(whole), frac) => gen64(whole, frac, "hours"), (Mins(whole), frac) => gen64(whole, frac, "minutes"), (Secs(whole), frac) => gen64(whole, frac, "seconds"), (Millis(whole), frac) => gen128(whole, frac, "milliseconds"), (Micros(whole), frac) => gen128(whole, frac, "microseconds"), (Nanos(whole), frac) => gen128(whole, frac, "nanoseconds"), } } /// Return a pair of (whole part, frac part) from a duration where. The whole /// part is the largest Unit containing a non-zero value, the frac part is a /// rational remainder left over. #[must_use] pub fn whole_and_frac(d: Duration) -> (Unit, f64) { use Unit::*; let whole = whole_unit(d); ( whole, match whole { Days(_) => (d.as_secs() % 86_400) as f64 / 86_400.0, Hours(_) => (d.as_secs() % 3_600) as f64 / 3_600.0, Mins(_) => (d.as_secs() % 60) as f64 / 60.0, Secs(_) => f64::from(d.subsec_millis()) / 1000.0, Millis(_) => f64::from(d.subsec_micros()) / 1000.0, Micros(_) => f64::from(d.subsec_nanos()) / 1000.0, Nanos(_) => 0.0, }, ) } /// Return the largest Unit which represents the duration. The value is /// rounded-down, but never zero. #[must_use] pub fn whole_unit(d: Duration) -> Unit { use Unit::*; match d.as_secs() { 86_400.. => Days(d.as_secs() / 86_400), 3_600..=86_399 => Hours(d.as_secs() / 3_600), 60..=3_599 => Mins(d.as_secs() / 60), _ => match d.as_micros() { 1_000_000.. => Secs(d.as_secs()), 1_000..=999_999 => Millis(d.subsec_millis().into()), _ => match d.as_nanos() { 1_000.. => Micros(d.subsec_micros().into()), _ => Nanos(d.subsec_nanos().into()), }, }, } } #[derive(Eq, PartialEq, Clone, Copy, Debug)] pub enum Unit { Days(u64), Hours(u64), Mins(u64), Secs(u64), Millis(u128), Micros(u128), Nanos(u128), }