use crate::core::duration::parse_duration_to_micros;
use crate::storage::query::condition::value::Value;
use reduct_base::error::ReductError;
pub(crate) fn parse_duration(duration_string: &str) -> Result<Value, ReductError> {
Ok(Value::Duration(parse_duration_to_micros(duration_string)?))
}
pub(super) fn fmt_duration(mut usec: i64, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut parts = Vec::new();
let units = [
("d", 86_400_000_000), ("h", 3_600_000_000), ("m", 60_000_000), ("s", 1_000_000), ("ms", 1000), ("us", 1), ];
for &(unit, unit_seconds) in &units {
if usec.abs() >= unit_seconds {
let value = usec / unit_seconds;
parts.push(format!("{}{}", value, unit));
usec -= value * unit_seconds;
}
}
if parts.is_empty() {
parts.push("0us".to_string());
}
write!(f, "{}", parts.join(" "))
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
#[rstest]
#[case(0, "0us")]
#[case(1, "1us")]
#[case(-1, "-1us")]
#[case(100, "100us")]
#[case(100_000, "100ms")]
#[case(1_000_000, "1s")]
#[case(-1_000_000, "-1s")]
#[case(60_000_000, "1m")]
#[case(3_600_000_000, "1h")]
#[case(86_400_000_000, "1d")]
#[case(86_400_000_000 + 3_600_000_000, "1d 1h")]
#[case(86_400_000_000 - 3_600_000_000 + 5, "23h 5us")]
fn test_fmt_duration(#[case] value: i64, #[case] literal: &str) {
let value = Value::Duration(value);
assert_eq!(parse_duration(literal).unwrap(), value);
assert_eq!(value.to_string(), literal);
}
#[rstest]
fn test_parse_invalid_duration() {
assert!(parse_duration("").is_err());
assert!(parse_duration("100xyz").is_err());
assert!(parse_duration("abc").is_err());
assert!(parse_duration("2.5m").is_err());
}
#[rstest]
fn test_parse_duration() {
assert_eq!(
parse_duration("100ms 500us").unwrap(),
Value::Duration(100_500)
);
assert_eq!(
parse_duration("1h -30m").unwrap(),
Value::Duration(1_800_000_000)
);
assert_eq!(
parse_duration("2d 3h").unwrap(),
Value::Duration(183_600_000_000)
);
}
#[rstest]
fn test_invalid_duration() {
assert!(parse_duration("").is_err());
assert!(parse_duration("1h 100xyz").is_err());
assert!(parse_duration("1h,2m").is_err());
}
}