use dates::Date;
use math::interpolation::Interpolable;
use std::cmp::Ordering;
use std::ops::Add;
use std::ops::AddAssign;
use std::fmt::Display;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum TimeOfDay {
Open,
EDSP,
Close
}
impl Display for TimeOfDay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TimeOfDay::Open => write!(f, "Open"),
TimeOfDay::Close => write!(f, "Close"),
TimeOfDay::EDSP => write!(f, "EDSP")
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DateTime {
date: Date,
time_of_day: TimeOfDay
}
impl DateTime {
pub fn new(date: Date, time_of_day: TimeOfDay) -> DateTime {
DateTime { date: date, time_of_day: time_of_day }
}
pub fn date(&self) -> Date { self.date }
pub fn time_of_day(&self) -> TimeOfDay { self.time_of_day }
}
impl Add<i32> for DateTime {
type Output = DateTime;
fn add(self, other: i32) -> DateTime {
DateTime::new(self.date + other, self.time_of_day)
}
}
impl AddAssign<i32> for DateTime {
fn add_assign(&mut self, other: i32) {
self.date += other;
}
}
impl Display for DateTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}/{}", self.date, self.time_of_day)
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct DateDayFraction {
date: Date,
day_fraction: f64
}
impl DateDayFraction {
pub fn new(date: Date, day_fraction: f64) -> DateDayFraction {
assert!(day_fraction >= 0.0 && day_fraction < 1.0);
DateDayFraction { date: date, day_fraction: day_fraction }
}
pub fn date(&self) -> Date { self.date }
pub fn day_fraction(&self) -> f64 { self.day_fraction }
}
impl Add<i32> for DateDayFraction {
type Output = DateDayFraction;
fn add(self, other: i32) -> DateDayFraction {
DateDayFraction::new(self.date + other, self.day_fraction)
}
}
impl AddAssign<i32> for DateDayFraction {
fn add_assign(&mut self, other: i32) {
self.date += other;
}
}
impl Ord for DateDayFraction {
fn cmp(&self, other: &DateDayFraction) -> Ordering {
self.partial_cmp(&other).expect("Non-orderable day fraction found in DateDayFraction")
}
}
impl Eq for DateDayFraction {}
impl Interpolable<DateDayFraction> for DateDayFraction {
fn interp_diff(&self, other: DateDayFraction) -> f64 {
(other.date - self.date) as f64
+ other.day_fraction - self.day_fraction
}
fn interp_cmp(&self, other: DateDayFraction) -> Ordering {
match self.partial_cmp(&other) {
Some(order) => order,
None => panic!("DateDayFraction contains NaN day-fraction")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn equality_and_order_for_date_times() {
let thursday = Date::from_ymd(2018, 05, 10);
let thursday_early = DateTime::new(thursday, TimeOfDay::Open);
let thursday_late = DateTime::new(thursday, TimeOfDay::Close);
let friday_early = DateTime::new(thursday + 1, TimeOfDay::EDSP);
let wednesday_late = DateTime::new(thursday - 1, TimeOfDay::Close);
let thursday_early2 = DateTime::new(thursday, TimeOfDay::Open);
assert!(thursday_early == thursday_early2);
assert!(thursday_early != friday_early);
assert!(thursday_late != thursday_early);
assert!(thursday_late < friday_early);
assert!(thursday_early < thursday_late);
assert!(wednesday_late < thursday_early);
assert!(friday_early > thursday_early);
assert!(thursday_late <= friday_early);
}
#[test]
fn equality_and_order_for_date_day_fractions() {
let thursday = Date::from_ymd(2018, 05, 10);
let thursday_early = DateDayFraction::new(thursday, 0.1);
let thursday_late = DateDayFraction::new(thursday, 0.9);
let friday_early = DateDayFraction::new(thursday + 1, 0.1);
let wednesday_late = DateDayFraction::new(thursday - 1, 0.9);
let thursday_early2 = DateDayFraction::new(thursday, 0.1);
assert!(thursday_early == thursday_early2);
assert!(thursday_early != friday_early);
assert!(thursday_late != thursday_early);
assert!(thursday_late < friday_early);
assert!(thursday_early < thursday_late);
assert!(wednesday_late < thursday_early);
assert!(friday_early > thursday_early);
assert!(thursday_late <= friday_early);
}
}