use std::time::Duration;
pub trait DurationExt {
fn seconds(self) -> Duration;
fn minutes(self) -> Duration;
fn hours(self) -> Duration;
fn milliseconds(self) -> Duration;
fn microseconds(self) -> Duration;
fn nanoseconds(self) -> Duration;
}
impl DurationExt for u64 {
fn seconds(self) -> Duration {
Duration::from_secs(self)
}
fn minutes(self) -> Duration {
let secs = self.checked_mul(60)
.expect(&format!("duration value {} minutes overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn hours(self) -> Duration {
let secs = self.checked_mul(3600)
.expect(&format!("duration value {} hours overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn milliseconds(self) -> Duration {
Duration::from_millis(self)
}
fn microseconds(self) -> Duration {
Duration::from_micros(self)
}
fn nanoseconds(self) -> Duration {
Duration::from_nanos(self)
}
}
impl DurationExt for u32 {
fn seconds(self) -> Duration {
Duration::from_secs(self as u64)
}
fn minutes(self) -> Duration {
(self as u64).minutes()
}
fn hours(self) -> Duration {
(self as u64).hours()
}
fn milliseconds(self) -> Duration {
Duration::from_millis(self as u64)
}
fn microseconds(self) -> Duration {
Duration::from_micros(self as u64)
}
fn nanoseconds(self) -> Duration {
Duration::from_nanos(self as u64)
}
}
impl DurationExt for i64 {
fn seconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} seconds", self);
Duration::from_secs(self as u64)
}
fn minutes(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} minutes", self);
(self as u64).minutes()
}
fn hours(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} hours", self);
(self as u64).hours()
}
fn milliseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} milliseconds", self);
Duration::from_millis(self as u64)
}
fn microseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} microseconds", self);
Duration::from_micros(self as u64)
}
fn nanoseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} nanoseconds", self);
Duration::from_nanos(self as u64)
}
}
impl DurationExt for i32 {
fn seconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} seconds", self);
Duration::from_secs(self as u64)
}
fn minutes(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} minutes", self);
(self as u64).minutes()
}
fn hours(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} hours", self);
(self as u64).hours()
}
fn milliseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} milliseconds", self);
Duration::from_millis(self as u64)
}
fn microseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} microseconds", self);
Duration::from_micros(self as u64)
}
fn nanoseconds(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} nanoseconds", self);
Duration::from_nanos(self as u64)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
const MAX_FOR_MINUTES: u64 = u64::MAX / 60;
const MAX_FOR_HOURS: u64 = u64::MAX / 3600;
const OVERFLOW_MINUTES: u64 = MAX_FOR_MINUTES + 1;
const OVERFLOW_HOURS: u64 = MAX_FOR_HOURS + 1;
#[test]
fn test_u64_large_units() {
let five: u64 = 5;
assert_eq!(five.minutes(), Duration::from_secs(5 * 60));
assert_eq!(five.hours(), Duration::from_secs(5 * 3600));
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_u64_minutes_panics_on_overflow() {
let _ = OVERFLOW_MINUTES.minutes();
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_u64_hours_panics_on_overflow() {
let _ = OVERFLOW_HOURS.hours();
}
#[test]
fn test_max_u64_small_units() {
let max_u64 = u64::MAX;
assert_eq!(max_u64.milliseconds(), Duration::from_millis(u64::MAX));
assert_eq!(max_u64.microseconds(), Duration::from_micros(u64::MAX));
assert_eq!(max_u64.nanoseconds(), Duration::from_nanos(u64::MAX));
}
#[test]
fn test_i64_positive() {
let pos: i64 = 10;
assert_eq!(pos.seconds(), Duration::from_secs(10));
assert_eq!(pos.minutes(), Duration::from_secs(600));
assert_eq!(pos.hours(), Duration::from_secs(36000));
}
#[test]
#[should_panic(expected = "duration cannot be negative")]
fn test_i64_negative_panics() {
let neg: i64 = -10;
let _ = neg.minutes();
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_i64_minutes_panics_on_overflow() {
let _ = (OVERFLOW_MINUTES as i64).minutes();
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_i64_hours_panics_on_overflow() {
let _ = (OVERFLOW_HOURS as i64).hours();
}
#[test]
fn test_i32_positive_full() {
let val: i32 = 5;
assert_eq!(val.seconds(), Duration::from_secs(5));
assert_eq!(val.minutes(), Duration::from_secs(300));
assert_eq!(val.hours(), Duration::from_secs(18000));
}
#[test]
#[should_panic(expected = "duration cannot be negative")]
fn test_i32_negative_panics() { let _ = (-5).seconds(); }
#[test]
fn test_u32_positive_full() {
let val: u32 = 5;
assert_eq!(val.seconds(), Duration::from_secs(5));
assert_eq!(val.minutes(), Duration::from_secs(300));
assert_eq!(val.hours(), Duration::from_secs(18000));
}
}