use std::time::Duration;
pub trait DurationExt {
fn seconds(self) -> Duration;
fn minutes(self) -> Duration;
fn hours(self) -> Duration;
fn days(self) -> Duration;
fn weeks(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 days(self) -> Duration {
let secs = self.checked_mul(86400)
.expect(&format!("duration value {} days overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn weeks(self) -> Duration {
let secs = self.checked_mul(604800)
.expect(&format!("duration value {} weeks 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 {
let secs = (self as u64).checked_mul(60)
.expect(&format!("duration value {} minutes overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn hours(self) -> Duration {
let secs = (self as u64).checked_mul(3600)
.expect(&format!("duration value {} hours overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn days(self) -> Duration {
let secs = (self as u64).checked_mul(86400)
.expect(&format!("duration value {} days overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn weeks(self) -> Duration {
let secs = (self as u64).checked_mul(604800)
.expect(&format!("duration value {} weeks overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
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);
let secs = (self as u64).checked_mul(60)
.expect(&format!("duration value {} minutes overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn hours(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} hours", self);
let secs = (self as u64).checked_mul(3600)
.expect(&format!("duration value {} hours overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn days(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} days", self);
let secs = (self as u64).checked_mul(86400)
.expect(&format!("duration value {} days overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn weeks(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} weeks", self);
let secs = (self as u64).checked_mul(604800)
.expect(&format!("duration value {} weeks overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
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);
let secs = (self as u64).checked_mul(60)
.expect(&format!("duration value {} minutes overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn hours(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} hours", self);
let secs = (self as u64).checked_mul(3600)
.expect(&format!("duration value {} hours overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn days(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} days", self);
let secs = (self as u64).checked_mul(86400)
.expect(&format!("duration value {} days overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
fn weeks(self) -> Duration {
assert!(self >= 0, "duration cannot be negative: got {} weeks", self);
let secs = (self as u64).checked_mul(604800)
.expect(&format!("duration value {} weeks overflows u64 seconds capacity", self));
Duration::from_secs(secs)
}
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 OVERFLOW_MINUTES: u64 = MAX_FOR_MINUTES.saturating_add(1);
#[test]
fn test_u64_large_units() {
let five: u64 = 5;
assert_eq!(five.minutes(), Duration::from_secs(5 * 60));
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_u64_minutes_panics_on_overflow() {
let _ = OVERFLOW_MINUTES.minutes();
}
#[test]
fn test_i64_positive() {
let pos_ten: i64 = 10;
assert_eq!(pos_ten.minutes(), Duration::from_secs(600));
}
#[test]
#[should_panic(expected = "duration cannot be negative")]
fn test_i64_negative_panics() {
let neg_ten: i64 = -10;
let _ = neg_ten.minutes();
}
#[test]
#[should_panic(expected = "overflows u64 seconds capacity")]
fn test_i64_minutes_panics_on_overflow() {
let _ = (OVERFLOW_MINUTES as i64).minutes();
}
#[test]
fn test_max_u64_small_units() {
let max_u64 = u64::MAX;
let small_duration = max_u64.milliseconds();
assert!(small_duration.as_millis() > 0);
}
}