//! The module for the TimeType
//!
use chrono::NaiveDateTime;
use std::ops::Add;
use std::ops::Sub;
use result::Result;
use error::KairosErrorKind as KEK;
use error::KairosError as KE;
use error_chain::ChainedError;
/// A Type of Time, currently based on chrono::NaiveDateTime
#[derive(Debug, Clone)]
pub enum TimeType {
Seconds(usize),
Minutes(usize),
Hours(usize),
Days(usize),
Weeks(usize),
Months(usize),
Years(usize),
Moment(NaiveDateTime),
Addition(Box<TimeType>, Box<TimeType>),
Subtraction(Box<TimeType>, Box<TimeType>),
}
impl Add for TimeType {
type Output = TimeType;
fn add(self, rhs: TimeType) -> Self::Output {
TimeType::Addition(Box::new(self), Box::new(rhs))
}
}
impl Sub for TimeType {
type Output = TimeType;
fn sub(self, rhs: TimeType) -> Self::Output {
TimeType::Subtraction(Box::new(self), Box::new(rhs))
}
}
impl TimeType {
fn calculate(self) -> Result<TimeType> {
use timetype::TimeType as TT;
match self {
TT::Addition(a, b) => add(a, b),
TT::Subtraction(a, b) => sub(a, b),
x => Ok(x)
}
}
}
fn add(a: Box<TimeType>, b: Box<TimeType>) -> Result<TimeType> {
use timetype::TimeType as TT;
match (*a, *b) {
(TT::Seconds(a), TT::Seconds(b)) => Ok(TT::Seconds(a + b)),
(TT::Minutes(a), TT::Minutes(b)) => Ok(TT::Minutes(a + b)),
(TT::Hours(a), TT::Hours(b)) => Ok(TT::Hours(a + b)),
(TT::Days(a), TT::Days(b)) => Ok(TT::Days(a + b)),
(TT::Weeks(a), TT::Weeks(b)) => Ok(TT::Weeks(a + b)),
(TT::Months(a), TT::Months(b)) => Ok(TT::Months(a + b)),
(TT::Years(a), TT::Years(b)) => Ok(TT::Years(a + b)),
(TT::Addition(a, b), other) => add(a, b)
.map(Box::new)
.and_then(|bx| add(bx, Box::new(other))),
(other, TT::Addition(a, b)) => add(a, b)
.map(Box::new)
.and_then(|bx| add(Box::new(other), bx)),
(thing, TT::Moment(mom)) => Err(KE::from_kind(KEK::CannotAdd(thing, TT::Moment(mom)))),
others => unimplemented!(),
}
}
fn sub(a: Box<TimeType>, b: Box<TimeType>) -> Result<TimeType> {
use timetype::TimeType as TT;
match (*a, *b) {
(TT::Seconds(a), TT::Seconds(b)) => Ok(TT::Seconds(a - b)),
(TT::Minutes(a), TT::Minutes(b)) => Ok(TT::Minutes(a - b)),
(TT::Hours(a), TT::Hours(b)) => Ok(TT::Hours(a - b)),
(TT::Days(a), TT::Days(b)) => Ok(TT::Days(a - b)),
(TT::Weeks(a), TT::Weeks(b)) => Ok(TT::Weeks(a - b)),
(TT::Months(a), TT::Months(b)) => Ok(TT::Months(a - b)),
(TT::Years(a), TT::Years(b)) => Ok(TT::