1#![allow(clippy::unwrap_used)]
2
3use std::time::Duration;
4
5pub use human_time_macros::elapsed;
6
7const UNITS: [(&str, u128); 6] = [
9 ("d", 86400000000), ("h", 3600000000), ("m", 60000000), ("s", 1000000), ("ms", 1000), ("μs", 1), ];
16
17pub trait ToHumanTimeString {
18 fn to_human_time_string(&self) -> String;
19 fn to_human_time_string_with_format<F, F1>(&self, time_fmt: F, res_fmt: F1) -> String
20 where
21 F: Fn(u128, &str) -> String,
22 F1: Fn(String, String) -> String;
23}
24
25impl ToHumanTimeString for Duration {
26 fn to_human_time_string(&self) -> String {
27 crate::human_time(*self)
28 }
29
30 fn to_human_time_string_with_format<F, F1>(&self, time_fmt: F, res_fmt: F1) -> String
31 where
32 F: Fn(u128, &str) -> String,
33 F1: Fn(String, String) -> String,
34 {
35 human_time_with_format(*self, time_fmt, res_fmt)
36 }
37}
38
39pub fn human_time(d: Duration) -> String {
40 human_time_with_format(
41 d,
42 |n, unit| format!("{}{}", n, unit),
43 |acc, item| format!("{},{}", acc, item),
44 )
45}
46
47pub fn human_time_with_format<F, F1>(d: Duration, time_fmt: F, res_fmt: F1) -> String
52where
53 F: Fn(u128, &str) -> String,
54 F1: Fn(String, String) -> String,
55{
56 let mut map: Vec<(u128, &str)> = Vec::new();
58 let mut μs = d.as_micros();
59 for (unit, n_μs) in UNITS {
60 map.push((μs / n_μs, unit));
61 μs %= n_μs;
62 }
63
64 match map
66 .into_iter()
67 .filter_map(|(n, u)| if n > 0 { Some(time_fmt(n, u)) } else { None })
68 .reduce(res_fmt)
69 {
70 Some(val) => val,
71 None => time_fmt(0, UNITS.last().unwrap().0),
73 }
74}