use crate::{FormatFloatValue, FormatIntegerValue, Unit};
const EPSILON: f64 = 1e-10;
#[derive(Debug, Default, PartialEq)]
pub struct Time {
pub days: u64,
pub hours: u8,
pub minutes: u8,
pub seconds: f64,
}
impl Time {
pub fn format_time(&self) -> String {
let mut parts = Vec::new();
if self.days > 0 {
parts.push(self.days.format_unit(Unit::Day));
}
if self.hours > 0 || !parts.is_empty() {
parts.push(self.hours.format_unit(Unit::Hour));
}
if self.minutes > 0 || !parts.is_empty() {
parts.push(self.minutes.format_unit(Unit::Minute));
}
let decimal: usize = self.calculate_decimal();
parts.push(self.seconds.format_float_unit(decimal, Unit::Second));
parts.join(", ")
}
fn calculate_decimal(&self) -> usize {
let sec = self.seconds;
if sec < EPSILON {
1
} else if sec >= 1.0 {
3
} else if sec >= 0.001 {
6
} else {
9
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::duration_extension::DurationExtension;
use std::time::Duration;
#[test]
fn times_new() {
let duration = Duration::from_secs(86400 + 3600 + 60 + 1); let time = duration.get_time();
assert_eq!(time.days, 1);
assert_eq!(time.hours, 1);
assert_eq!(time.minutes, 1);
assert_eq!(time.seconds, 1.0);
let duration = Duration::from_secs_f64(3661.5); let time = duration.get_time();
assert_eq!(time.days, 0);
assert_eq!(time.hours, 1);
assert_eq!(time.minutes, 1);
assert_eq!(time.seconds, 1.5);
let duration = Duration::from_secs(0);
let time = duration.get_time();
assert_eq!(time.days, 0);
assert_eq!(time.hours, 0);
assert_eq!(time.minutes, 0);
assert_eq!(time.seconds, 0.0);
let duration = Duration::from_secs_f64(2.5 * 86400.0);
let time = duration.get_time();
assert_eq!(time.days, 2);
assert_eq!(time.hours, 12);
assert_eq!(time.minutes, 0);
assert_eq!(time.seconds, 0.0);
}
#[test]
fn times_format() {
let time = Time {
days: 1,
hours: 2,
minutes: 3,
seconds: 4.567002,
};
assert_eq!(
time.format_time(),
"1 day, 2 hours, 3 minutes, 4.567 seconds"
);
let time = Time {
days: 0,
hours: 2,
minutes: 3,
seconds: 4.567,
};
assert_eq!(time.format_time(), "2 hours, 3 minutes, 4.567 seconds");
let time = Time {
days: 0,
hours: 0,
minutes: 3,
seconds: 4.567111,
};
assert_eq!(time.format_time(), "3 minutes, 4.567 seconds");
let time = Time {
days: 0,
hours: 0,
minutes: 0,
seconds: 4.567000444,
};
assert_eq!(time.format_time(), "4.567 seconds");
let time = Time {
days: 1,
hours: 0,
minutes: 0,
seconds: 0.0,
};
assert_eq!(time.format_time(), "1 day, 0 hour, 0 minute, 0.0 second");
let time = Time {
days: 1,
hours: 2,
minutes: 0,
seconds: 0.0,
};
assert_eq!(time.format_time(), "1 day, 2 hours, 0 minute, 0.0 second");
}
#[test]
fn times_default() {
let time = Time {
days: 0,
hours: 0,
minutes: 0,
seconds: 0.0,
};
let time_default = Time::default();
assert_eq!(time, time_default);
assert_eq!(time.format_time(), "0.0 second");
}
}