1use std::time::Duration as StdDuration;
8
9use time::format_description::well_known::Rfc3339;
10use time::OffsetDateTime;
11
12pub(crate) fn format_timestamp_rfc3339(value: OffsetDateTime) -> String {
15 value.format(&Rfc3339).unwrap_or_else(|_| value.to_string())
16}
17
18pub(crate) fn format_unix_ms_rfc3339(ms: i64) -> String {
20 let seconds = ms.div_euclid(1000);
21 let value = OffsetDateTime::from_unix_timestamp(seconds).unwrap_or(OffsetDateTime::UNIX_EPOCH);
22 format_timestamp_rfc3339(value)
23}
24
25pub(crate) fn format_duration_coarse(value: StdDuration) -> String {
30 if value.as_secs() == 0 {
31 return format!("{}ms", value.as_millis());
32 }
33 let seconds = value.as_secs();
34 if seconds < 60 {
35 return format!("{seconds}s");
36 }
37 if seconds < 60 * 60 {
38 return format!("{}m", seconds / 60);
39 }
40 if seconds < 60 * 60 * 24 {
41 return format!("{}h", seconds / (60 * 60));
42 }
43 if seconds < 60 * 60 * 24 * 7 {
44 return format!("{}d", seconds / (60 * 60 * 24));
45 }
46 if seconds.is_multiple_of(60 * 60 * 24 * 7) {
47 return format!("{}w", seconds / (60 * 60 * 24 * 7));
48 }
49 format!("{}d", seconds / (60 * 60 * 24))
50}
51
52pub(crate) fn format_duration_ms(duration_ms: u64) -> String {
55 if duration_ms >= 60_000 {
56 format!("{:.1}m", duration_ms as f64 / 60_000.0)
57 } else if duration_ms >= 1_000 {
58 format!("{:.1}s", duration_ms as f64 / 1_000.0)
59 } else {
60 format!("{duration_ms}ms")
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn timestamp_uses_rfc3339() {
70 let value = OffsetDateTime::UNIX_EPOCH;
71 assert_eq!(format_timestamp_rfc3339(value), "1970-01-01T00:00:00Z");
72 }
73
74 #[test]
75 fn unix_ms_rounds_to_seconds() {
76 assert_eq!(format_unix_ms_rfc3339(0), "1970-01-01T00:00:00Z");
77 assert_eq!(format_unix_ms_rfc3339(1500), "1970-01-01T00:00:01Z");
78 assert_eq!(format_unix_ms_rfc3339(-1), "1969-12-31T23:59:59Z");
80 }
81
82 #[test]
83 fn coarse_duration_picks_a_unit() {
84 assert_eq!(format_duration_coarse(StdDuration::from_millis(0)), "0ms");
85 assert_eq!(format_duration_coarse(StdDuration::from_secs(5)), "5s");
86 assert_eq!(format_duration_coarse(StdDuration::from_secs(120)), "2m");
87 assert_eq!(format_duration_coarse(StdDuration::from_secs(7200)), "2h");
88 assert_eq!(
89 format_duration_coarse(StdDuration::from_secs(86_400 * 3)),
90 "3d"
91 );
92 assert_eq!(
93 format_duration_coarse(StdDuration::from_secs(86_400 * 14)),
94 "2w"
95 );
96 }
97
98 #[test]
99 fn ms_duration_uses_one_decimal_above_a_second() {
100 assert_eq!(format_duration_ms(500), "500ms");
101 assert_eq!(format_duration_ms(1_500), "1.5s");
102 assert_eq!(format_duration_ms(90_000), "1.5m");
103 }
104}