use std::time::Duration;
const YEAR: u128 = 31_557_600_000;
const MONTH: u128 = 2_629_800_000;
const WEEK: u128 = 604_800_000;
const DAY: u128 = 86_400_000;
const HOUR: u128 = 3_600_000;
const MINUTE: u128 = 60_000;
const SECOND: u128 = 1_000;
const MILLISECOND: u128 = 1;
const UNITS: [(u128, &str); 8] = [
(YEAR, "y"),
(MONTH, "mo"),
(WEEK, "w"),
(DAY, "d"),
(HOUR, "h"),
(MINUTE, "m"),
(SECOND, "s"),
(MILLISECOND, "ms"),
];
#[must_use]
pub fn pretty_print(
d: &Duration,
min_resolution: &str,
separator: &str,
) -> String {
components(d, min_resolution).join(separator)
}
#[must_use]
pub fn components(d: &Duration, min_resolution: &str) -> Vec<String> {
let mut d = d.as_millis();
let mut out = vec![];
for (millis, suffix) in UNITS {
if d < millis {
continue;
}
let units = d / millis;
out.push(format!("{}{}", units, suffix));
d = d
.checked_sub(units.checked_mul(millis).expect("overflow"))
.expect("overflow");
if suffix == min_resolution {
break;
}
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pretty_print() {
assert_eq!(pretty_print(&Duration::from_secs(0), "ms", ""), "");
assert_eq!(
pretty_print(&Duration::from_millis(YEAR as u64 / 2), "ms", ","),
"6mo"
);
assert_eq!(
pretty_print(&Duration::from_millis(YEAR as u64), "ms", ","),
"1y"
);
assert_eq!(
pretty_print(&Duration::from_millis(YEAR as u64 + 1), "ms", ","),
"1y,1ms"
);
assert_eq!(
pretty_print(&Duration::from_millis(YEAR as u64 - 1), "ms", ", "),
"11mo, 4w, 2d, 10h, 29m, 59s, 999ms"
);
assert_eq!(
pretty_print(&Duration::from_millis(2 * YEAR as u64), "ms", ""),
"2y"
);
assert_eq!(
pretty_print(&Duration::from_millis(YEAR as u64 - 1), "h", "-"),
"11mo-4w-2d-10h"
);
}
#[test]
fn test_components() {
let empty: Vec<String> = vec![];
assert_eq!(components(&Duration::from_secs(0), "ms"), empty);
assert_eq!(
components(&Duration::from_millis(YEAR as u64 / 2), "ms"),
vec!["6mo"]
);
assert_eq!(
components(&Duration::from_millis(YEAR as u64), "ms"),
vec!["1y"]
);
assert_eq!(
components(&Duration::from_millis(YEAR as u64 + 1), "ms"),
vec!["1y", "1ms"]
);
assert_eq!(
components(&Duration::from_millis(YEAR as u64 - 1), "ms"),
vec!["11mo", "4w", "2d", "10h", "29m", "59s", "999ms"]
);
assert_eq!(
components(&Duration::from_millis(2 * YEAR as u64), "ms"),
vec!["2y"]
);
assert_eq!(
components(&Duration::from_millis(YEAR as u64 - 1), "h"),
vec!["11mo", "4w", "2d", "10h"]
);
}
}