haz_cli/output/
duration.rs1use std::time::Duration;
20
21#[must_use]
24pub fn format_duration(duration: Duration) -> String {
25 let total_secs = duration.as_secs();
26 let sub_secs_millis = duration.subsec_millis();
27
28 if total_secs == 0 {
29 let min_millis = u32::from(!duration.is_zero());
33 let millis = sub_secs_millis.max(min_millis);
34 return format!("{millis}ms");
35 }
36
37 if total_secs < 60 {
38 return format!("{total_secs}s {sub_secs_millis}ms");
39 }
40
41 let total_minutes = total_secs / 60;
42 let seconds_part = total_secs % 60;
43 if total_minutes < 60 {
44 return format!("{total_minutes}m {seconds_part}s");
45 }
46
47 let total_hours = total_minutes / 60;
48 let minutes_part = total_minutes % 60;
49 format!("{total_hours}h {minutes_part}m")
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn sub_millisecond_renders_as_one_ms() {
58 assert_eq!(format_duration(Duration::from_micros(500)), "1ms");
59 }
60
61 #[test]
62 fn zero_renders_as_zero_ms() {
63 assert_eq!(format_duration(Duration::ZERO), "0ms");
64 }
65
66 #[test]
67 fn millisecond_grain_under_one_second() {
68 assert_eq!(format_duration(Duration::from_millis(176)), "176ms");
69 assert_eq!(format_duration(Duration::from_millis(999)), "999ms");
70 }
71
72 #[test]
73 fn second_plus_millisecond_under_one_minute() {
74 assert_eq!(format_duration(Duration::from_millis(7_856)), "7s 856ms");
75 assert_eq!(format_duration(Duration::from_secs(1)), "1s 0ms");
76 assert_eq!(format_duration(Duration::from_millis(59_999)), "59s 999ms");
77 }
78
79 #[test]
80 fn minute_plus_second_under_one_hour() {
81 assert_eq!(format_duration(Duration::from_mins(1)), "1m 0s");
82 assert_eq!(format_duration(Duration::from_secs(83)), "1m 23s");
83 assert_eq!(format_duration(Duration::from_secs(3_599)), "59m 59s");
84 }
85
86 #[test]
87 fn hour_plus_minute() {
88 assert_eq!(format_duration(Duration::from_hours(1)), "1h 0m");
89 assert_eq!(format_duration(Duration::from_mins(83)), "1h 23m");
90 }
91}