use chrono::Duration;
use nutype::nutype;
#[nutype(
validate(greater = 0, less_or_equal = 8760),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
Hash
)
)]
pub struct Hours(i64);
impl Hours {
pub fn one() -> Self {
Self::try_new(1).unwrap()
}
pub fn one_day() -> Self {
Self::try_new(24).unwrap()
}
pub fn one_week() -> Self {
Self::try_new(168).unwrap()
}
pub fn to_duration(&self) -> Duration {
Duration::hours(self.into_inner())
}
}
#[nutype(
validate(greater = 0, less_or_equal = 3650),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
Hash
)
)]
pub struct Days(i64);
impl Days {
pub fn one() -> Self {
Self::try_new(1).unwrap()
}
pub fn one_week() -> Self {
Self::try_new(7).unwrap()
}
pub fn one_month() -> Self {
Self::try_new(30).unwrap()
}
pub fn one_quarter() -> Self {
Self::try_new(90).unwrap()
}
pub fn one_year() -> Self {
Self::try_new(365).unwrap()
}
pub fn to_duration(&self) -> Duration {
Duration::days(self.into_inner())
}
pub fn to_hours(&self) -> i64 {
self.into_inner() * 24
}
}
#[nutype(
validate(greater = 0, less_or_equal = 10080),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
Hash
)
)]
pub struct Minutes(i64);
impl Minutes {
pub fn one() -> Self {
Self::try_new(1).unwrap()
}
pub fn five() -> Self {
Self::try_new(5).unwrap()
}
pub fn one_hour() -> Self {
Self::try_new(60).unwrap()
}
pub fn to_duration(&self) -> Duration {
Duration::minutes(self.into_inner())
}
}
#[nutype(
validate(greater_or_equal = 0),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
Hash
)
)]
pub struct EpochSeconds(i64);
impl EpochSeconds {
pub fn year_2000() -> Self {
Self::try_new(946684800).unwrap()
}
pub fn year_2020() -> Self {
Self::try_new(1577836800).unwrap()
}
pub fn year_2024() -> Self {
Self::try_new(1704067200).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hours_validation() {
assert!(Hours::try_new(1).is_ok());
assert!(Hours::try_new(24).is_ok());
assert!(Hours::try_new(8760).is_ok());
assert!(Hours::try_new(0).is_err());
assert!(Hours::try_new(8761).is_err());
}
#[test]
fn test_days_validation() {
assert!(Days::try_new(1).is_ok());
assert!(Days::try_new(365).is_ok());
assert!(Days::try_new(3650).is_ok());
assert!(Days::try_new(0).is_err());
assert!(Days::try_new(3651).is_err());
}
#[test]
fn test_minutes_validation() {
assert!(Minutes::try_new(1).is_ok());
assert!(Minutes::try_new(60).is_ok());
assert!(Minutes::try_new(10080).is_ok());
assert!(Minutes::try_new(0).is_err());
assert!(Minutes::try_new(10081).is_err());
}
#[test]
fn test_duration_conversions() {
assert_eq!(Hours::one_day().to_duration(), Duration::hours(24));
assert_eq!(Days::one_week().to_duration(), Duration::days(7));
assert_eq!(Minutes::one_hour().to_duration(), Duration::minutes(60));
assert_eq!(Days::one_week().to_hours(), 168);
}
}