Moving back to single dates for calendar

This commit is contained in:
Ian Roddis
2021-12-08 10:45:24 -04:00
parent c4f87e1e9e
commit fde7a01e99

View File

@@ -1,4 +1,3 @@
use crate::date_range::*;
use chrono::naive::NaiveDate; use chrono::naive::NaiveDate;
use chrono::{Datelike, Month, Weekday}; use chrono::{Datelike, Month, Weekday};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -9,10 +8,9 @@ use std::collections::HashSet;
- workdays are only calculated within a year. If a workday in a prior - workdays are only calculated within a year. If a workday in a prior
year is bumped to the next year, it won't be considered. year is bumped to the next year, it won't be considered.
- workday impact is searched forward. If there is a mix of AdjustmentPolicy's - workday impact is searched forward. If there is a mix of AdjustmentPolicies
then some weird stuff can happen (workdays occur A, B, but end up getting then some weird stuff can happen (workdays occur A, B, but end up getting
observed B, A) observed B, A)
- No support for workday ranges (e.g. Golden Week)
*/ */
#[derive(Copy, Clone, Serialize, Deserialize, Debug)] #[derive(Copy, Clone, Serialize, Deserialize, Debug)]
@@ -45,9 +43,9 @@ pub enum DateSpec {
#[serde(default)] #[serde(default)]
description: String, description: String,
#[serde(default)] #[serde(default)]
since: Option<NaiveDate>, valid_since: Option<NaiveDate>,
#[serde(default)] #[serde(default)]
until: Option<NaiveDate>, valid_until: Option<NaiveDate>,
}, },
NthDayOccurance { NthDayOccurance {
month: Month, month: Month,
@@ -58,51 +56,48 @@ pub enum DateSpec {
#[serde(default)] #[serde(default)]
description: String, description: String,
#[serde(default)] #[serde(default)]
since: Option<NaiveDate>, valid_since: Option<NaiveDate>,
#[serde(default)] #[serde(default)]
until: Option<NaiveDate>, valid_until: Option<NaiveDate>,
}, },
} }
impl DateSpec { impl DateSpec {
/// Get exact date of event and its policy, if it occured in that year /// Get exact date of event and its policy, if it occured in that year
fn resolve(&self, year: i32) -> Option<(DateRange, AdjustmentPolicy)> { fn resolve(&self, year: i32) -> Option<(NaiveDate, AdjustmentPolicy)> {
use DateSpec::*; use DateSpec::*;
match self { match self {
SpecificDate { date, .. } => Some(( SpecificDate { date, .. } => Some((*date, AdjustmentPolicy::NoAdjustment)),
DateRange::new(*date, date.succ()),
AdjustmentPolicy::NoAdjustment,
)),
DayOfMonth { DayOfMonth {
month, month,
day, day,
since, valid_since,
until, valid_until,
observed, observed,
.. ..
} => { } => {
if since.is_some() && since.unwrap().year() > year { if valid_since.is_some() && valid_since.unwrap().year() > year {
None None
} else if until.is_some() && until.unwrap().year() < year { } else if valid_until.is_some() && valid_until.unwrap().year() < year {
None None
} else { } else {
let date = NaiveDate::from_ymd(year, month.number_from_month(), *day); let date = NaiveDate::from_ymd(year, month.number_from_month(), *day);
Some((DateRange::new(date, date.succ()), *observed)) Some((date, *observed))
} }
} }
NthDayOccurance { NthDayOccurance {
month, month,
dow, dow,
offset, offset,
since, valid_since,
until, valid_until,
observed, observed,
.. ..
} => { } => {
if since.is_some() && since.unwrap().year() > year { if valid_since.is_some() && valid_since.unwrap().year() > year {
None None
} else if until.is_some() && until.unwrap().year() < year { } else if valid_until.is_some() && valid_until.unwrap().year() < year {
None None
} else { } else {
let month_num = month.number_from_month(); let month_num = month.number_from_month();
@@ -120,7 +115,7 @@ impl DateSpec {
date = date.checked_sub_signed(chrono::Duration::days(7)).unwrap(); date = date.checked_sub_signed(chrono::Duration::days(7)).unwrap();
off += 1; off += 1;
} }
Some((DateRange::new(date, date.succ()), *observed)) Some((date, *observed))
} else { } else {
let mut date = NaiveDate::from_ymd(year, month_num, 1); let mut date = NaiveDate::from_ymd(year, month_num, 1);
while date.weekday() != *dow { while date.weekday() != *dow {
@@ -131,7 +126,7 @@ impl DateSpec {
date = date.checked_add_signed(chrono::Duration::days(7)).unwrap(); date = date.checked_add_signed(chrono::Duration::days(7)).unwrap();
off -= 1; off -= 1;
} }
Some((DateRange::new(date, date.succ()), *observed)) Some((date, *observed))
} }
} }
} }
@@ -159,17 +154,15 @@ pub struct Calendar {
} }
impl Calendar { impl Calendar {
fn adjust_workdays(&self, workdays: &Vec<(DateRange, AdjustmentPolicy)>) -> HashSet<NaiveDate> { fn adjust_workdays(&self, workdays: &Vec<(NaiveDate, AdjustmentPolicy)>) -> HashSet<NaiveDate> {
let mut observed = HashSet::new(); let mut observed = HashSet::new();
for (date_range, policy) in workdays.iter() { for (date, policy) in workdays.iter() {
for date in date_range { match self.adjust_workday(*date, policy, &observed) {
match self.adjust_workday(date, policy, &observed) { Some(workday) => {
Some(workday) => { observed.insert(workday);
observed.insert(workday);
}
None => {}
} }
None => {}
} }
} }
@@ -229,7 +222,7 @@ impl Calendar {
/// Get the set of all workdays in a given year /// Get the set of all workdays in a given year
pub fn get_workdays(&self, date: NaiveDate) -> HashSet<NaiveDate> { pub fn get_workdays(&self, date: NaiveDate) -> HashSet<NaiveDate> {
let workdays: Vec<(DateRange, AdjustmentPolicy)> = self let workdays: Vec<(NaiveDate, AdjustmentPolicy)> = self
.exclude .exclude
.iter() .iter()
.map(|x| x.resolve(date.year())) .map(|x| x.resolve(date.year()))
@@ -284,16 +277,16 @@ mod tests {
day: 25u32, day: 25u32,
observed: AdjustmentPolicy::Next, observed: AdjustmentPolicy::Next,
description: "Christmas".to_owned(), description: "Christmas".to_owned(),
since: None, valid_since: None,
until: None, valid_until: None,
}, },
DateSpec::DayOfMonth { DateSpec::DayOfMonth {
month: December, month: December,
day: 26u32, day: 26u32,
observed: AdjustmentPolicy::Next, observed: AdjustmentPolicy::Next,
description: "Boxing Day".to_owned(), description: "Boxing Day".to_owned(),
since: None, valid_since: None,
until: None, valid_until: None,
}, },
], ],
inherits: vec![], inherits: vec![],
@@ -323,24 +316,24 @@ mod tests {
day: 25u32, day: 25u32,
observed: AdjustmentPolicy::Next, observed: AdjustmentPolicy::Next,
description: "Christmas".to_owned(), description: "Christmas".to_owned(),
since: None, valid_since: None,
until: None, valid_until: None,
}, },
DateSpec::DayOfMonth { DateSpec::DayOfMonth {
month: December, month: December,
day: 26u32, day: 26u32,
observed: AdjustmentPolicy::Next, observed: AdjustmentPolicy::Next,
description: "Boxing Day".to_owned(), description: "Boxing Day".to_owned(),
since: None, valid_since: None,
until: None, valid_until: None,
}, },
DateSpec::DayOfMonth { DateSpec::DayOfMonth {
month: January, month: January,
day: 1u32, day: 1u32,
observed: AdjustmentPolicy::Next, observed: AdjustmentPolicy::Next,
description: "New Years Day".to_owned(), description: "New Years Day".to_owned(),
since: None, valid_since: None,
until: None, valid_until: None,
}, },
], ],
inherits: vec![], inherits: vec![],