1use time::{format_description, OffsetDateTime};
16
17const SECOND: i64 = 1000;
18const MINUTE: i64 = SECOND * 60;
19const HOUR: i64 = MINUTE * 60;
20const DAY: i64 = HOUR * 24;
21
22pub fn human_duration(duration_millis: i64) -> String {
23 if duration_millis > DAY {
24 format!("{:.2} days", duration_millis as f64 / DAY as f64)
25 } else if duration_millis > HOUR {
26 format!("{:.2} hours", duration_millis as f64 / HOUR as f64)
27 } else if duration_millis > MINUTE {
28 format!("{:.2} minutes", duration_millis as f64 / MINUTE as f64)
29 } else if duration_millis > SECOND {
30 format!("{:.2} seconds", duration_millis as f64 / SECOND as f64)
31 } else {
32 format!("{duration_millis:.2} milliseconds")
33 }
34}
35
36pub fn human_time(ts_milli: i64) -> String {
37 let ts = ts_milli / 1000;
38 let naive = OffsetDateTime::from_unix_timestamp(ts);
39 if let Ok(result) = naive {
40 let format =
41 format_description::parse("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]Z")
42 .expect("unable to setup format");
43 result.format(&format).expect("unable to handle format")
44 } else {
45 "".to_string()
46 }
47}
48
49pub fn human_percentage(perc: f64) -> String {
50 if perc.is_nan() {
51 return "0.00%".to_string();
52 }
53 format!("{:.2}%", perc * 100.00)
54}
55
56pub fn human_bytes_i128(bytes: i128) -> String {
57 if bytes > 1024 * 1024 * 1024 * 1024 {
58 return format!(
59 "{:.2} tb",
60 bytes as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
61 );
62 } else if bytes > 1024 * 1024 * 1024 {
63 return format!("{:.2} gb", bytes as f64 / (1024.0 * 1024.0 * 1024.0));
64 } else if bytes > 1024 * 1024 {
65 return format!("{:.2} mb", bytes as f64 / (1024.0 * 1024.0));
66 } else if bytes > 1024 {
67 return format!("{:.2} kb", bytes as f64 / 1024.0);
68 }
69 format!("{bytes:.2} bytes")
70}
71
72pub fn human_bytes(bytes: i64) -> String {
73 if bytes > 1024 * 1024 * 1024 * 1024 {
74 return format!(
75 "{:.2} tb",
76 bytes as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
77 );
78 } else if bytes > 1024 * 1024 * 1024 {
79 return format!("{:.2} gb", bytes as f64 / (1024.0 * 1024.0 * 1024.0));
80 } else if bytes > 1024 * 1024 {
81 return format!("{:.2} mb", bytes as f64 / (1024.0 * 1024.0));
82 } else if bytes > 1024 {
83 return format!("{:.2} kb", bytes as f64 / 1024.0);
84 }
85 format!("{bytes:.2} bytes")
86}
87
88pub fn human_bytes_base_1k(bytes: i64) -> String {
89 let base = 1000.0;
90 let base_i64 = 1000;
91 if bytes > base_i64 * base_i64 * base_i64 * base_i64 {
92 return format!("{:.2} tb", bytes as f64 / (base * base * base * base));
93 } else if bytes > base_i64 * base_i64 * base_i64 {
94 let gb = bytes as f64 / (base * base * base);
95 return format!("{gb:.2} gb");
96 } else if bytes > base_i64 * base_i64 {
97 return format!("{:.2} mb", bytes as f64 / (base * base));
98 } else if bytes > base_i64 {
99 return format!("{:.2} kb", bytes as f64 / base);
100 }
101 format!("{bytes:.2} bytes")
102}
103
104pub fn human_metric(metric_name: String, value: i64) -> String {
105 if metric_name.ends_with("BYTES_READ") {
106 return human_bytes(value);
107 } else if metric_name.ends_with("_NS") {
108 return human_duration(value / 1000000);
109 }
110 "".to_string()
111}