zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use std::fmt;
use std::time::Duration;

use num_format::ToFormattedString;
use num_traits::ToPrimitive;
// use rust_decimal::prelude::FromPrimitive;

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
    }
}

/// A wrapper type that allows you to Display a Duration
#[derive(Debug, Clone)]
pub struct FormattedDuration(Duration);

impl FormattedDuration {
    /// Returns a reference to the [`Duration`][] that is being formatted.
    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; // 365.25d
        let ydays = secs % 31_557_600;
        let months = ydays / 2_630_016; // 30.44d
        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(())
    }
}