guardy 0.2.4

Fast, secure git hooks in Rust with secret scanning and protected file synchronization
Documentation
use std::time::Duration;

/// Format time duration intelligently with appropriate units and precision
///
/// Automatically selects the most appropriate unit based on duration:
/// - < 1µs: Show as nanoseconds (e.g., "123ns")
/// - < 1ms: Show as microseconds (e.g., "456µs")
/// - < 1s: Show as milliseconds (e.g., "38ms")
/// - < 10s: Show as seconds with precision (e.g., "1.234s")
/// - >= 10s: Show as minutes:seconds with precision (e.g., "1m 4.494s")
pub fn format_time(duration: Duration) -> String {
    let total_ns = duration.as_nanos();

    // Use nanoseconds for very small durations
    if total_ns < 1_000 {
        format!("{total_ns}ns")
    }
    // Use microseconds for small durations
    else if total_ns < 1_000_000 {
        let us = total_ns as f64 / 1_000.0;
        if us < 10.0 {
            format!("{us:.3}µs")
        } else {
            format!("{us:.1}µs")
        }
    }
    // Use milliseconds for medium durations
    else if total_ns < 1_000_000_000 {
        let ms = total_ns as f64 / 1_000_000.0;
        if ms < 10.0 {
            format!("{ms:.3}ms")
        } else {
            format!("{ms:.0}ms")
        }
    }
    // Use seconds with precision for times under 10 seconds
    else if total_ns < 10_000_000_000 {
        let seconds = duration.as_secs_f64();
        format!("{seconds:.3}s")
    }
    // For longer times, show minutes:seconds with precision
    else {
        let total_seconds = duration.as_secs_f64();
        let minutes = (total_seconds / 60.0) as u64;
        let remaining_seconds = total_seconds % 60.0;

        if minutes > 0 {
            format!("{minutes}m {remaining_seconds:.3}s")
        } else {
            format!("{remaining_seconds:.3}s")
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_format_time_nanoseconds() {
        assert_eq!(format_time(Duration::from_nanos(123)), "123ns");
        assert_eq!(format_time(Duration::from_nanos(999)), "999ns");
    }

    #[test]
    fn test_format_time_microseconds() {
        assert_eq!(format_time(Duration::from_nanos(1_234)), "1.234µs");
        assert_eq!(format_time(Duration::from_nanos(9_876)), "9.876µs");
        assert_eq!(format_time(Duration::from_micros(12)), "12.0µs");
        assert_eq!(format_time(Duration::from_micros(123)), "123.0µs");
    }

    #[test]
    fn test_format_time_milliseconds() {
        assert_eq!(format_time(Duration::from_micros(1_234)), "1.234ms");
        assert_eq!(format_time(Duration::from_millis(38)), "38ms");
        assert_eq!(format_time(Duration::from_millis(123)), "123ms");
        assert_eq!(format_time(Duration::from_millis(999)), "999ms");
    }

    #[test]
    fn test_format_time_seconds() {
        assert_eq!(format_time(Duration::from_millis(1234)), "1.234s");
        assert_eq!(format_time(Duration::from_millis(5678)), "5.678s");
        assert_eq!(format_time(Duration::from_millis(9999)), "9.999s");
    }

    #[test]
    fn test_format_time_minutes() {
        assert_eq!(format_time(Duration::from_millis(64494)), "1m 4.494s");
        assert_eq!(format_time(Duration::from_millis(125000)), "2m 5.000s");
        assert_eq!(format_time(Duration::from_millis(3661000)), "61m 1.000s");
    }
}