use std::fmt;
use std::time::Duration;
use num_format::ToFormattedString;
use num_traits::ToPrimitive;
use human_bytes::human_bytes;
pub fn format_duration_secs(seconds: u64) -> String {
format!("{}", format_duration(Duration::from_secs(seconds)))
}
pub fn format_duration_millis(millis: u64) -> String {
format!("{}", format_duration(Duration::from_millis(millis)))
}
pub fn format_duration_micros(micros: u64) -> String {
format!("{}", format_duration(Duration::from_micros(micros)))
}
pub fn format_duration_nanos(nanos: u64) -> String {
format!("{}", format_duration(Duration::from_nanos(nanos)))
}
pub fn format_duration(val: Duration) -> FormattedDuration {
FormattedDuration(val)
}
pub fn format_bytes_size(size: usize) -> String {
human_bytes(size as f64).replace(' ', "")
}
pub fn format_decimal(value: rust_decimal::Decimal, scale: u32) -> String {
let rounded = value.round_dp(scale);
let int_part = rounded.trunc().to_i64().unwrap();
let int_str = int_part.to_formatted_string(&num_format::Locale::en);
if scale > 0 {
let frac_str = format!("{:.*}", scale as usize, rounded.fract().abs())
.split('.')
.nth(1)
.unwrap()
.to_string();
format!("{}.{}", int_str, frac_str)
} else {
int_str
}
}
#[derive(Debug, Clone)]
pub struct FormattedDuration(Duration);
impl FormattedDuration {
pub fn get_ref(&self) -> &Duration {
&self.0
}
pub fn item_plural(
&self,
f: &mut fmt::Formatter,
started: &mut bool,
name: &str,
value: u64,
) -> fmt::Result {
if value > 0 {
if *started {
f.write_str("")?;
}
write!(f, "{}{}", value, name)?;
if value > 1 {
f.write_str("s")?;
}
*started = true;
}
Ok(())
}
pub fn item(
&self,
f: &mut fmt::Formatter,
started: &mut bool,
name: &str,
value: u32,
) -> fmt::Result {
if value > 0 {
if *started {
f.write_str("")?;
}
write!(f, "{}{}", value, name)?;
*started = true;
}
Ok(())
}
}
impl fmt::Display for FormattedDuration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let secs = self.0.as_secs();
let nanos = self.0.subsec_nanos();
if secs == 0 && nanos == 0 {
f.write_str("0s")?;
return Ok(());
}
let years = secs / 31_557_600; let ydays = secs % 31_557_600;
let months = ydays / 2_630_016; let mdays = ydays % 2_630_016;
let days = mdays / 86400;
let day_secs = mdays % 86400;
let hours = day_secs / 3600;
let minutes = day_secs % 3600 / 60;
let seconds = day_secs % 60;
let millis = nanos / 1_000_000;
let micros = nanos / 1000 % 1000;
let nanosec = nanos % 1000;
let started = &mut false;
self.item_plural(f, started, "year", years)?;
self.item_plural(f, started, "month", months)?;
self.item_plural(f, started, "day", days)?;
self.item(f, started, "h", hours as u32)?;
self.item(f, started, "m", minutes as u32)?;
self.item(f, started, "s", seconds as u32)?;
self.item(f, started, "ms", millis)?;
self.item(f, started, "µs", micros)?;
self.item(f, started, "ns", nanosec)?;
Ok(())
}
}