75 lines
2.2 KiB
Rust
75 lines
2.2 KiB
Rust
use std::cmp;
|
|
use std::ops::RangeInclusive;
|
|
|
|
use chrono::{Datelike, Duration, NaiveDate};
|
|
|
|
use super::delta::Delta;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct DateRange {
|
|
from: NaiveDate,
|
|
until: NaiveDate,
|
|
}
|
|
|
|
impl DateRange {
|
|
pub fn new(from: NaiveDate, until: NaiveDate) -> Option<Self> {
|
|
if from <= until {
|
|
Some(Self { from, until })
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn with_from(&self, from: NaiveDate) -> Option<Self> {
|
|
Self::new(from, self.until)
|
|
}
|
|
|
|
pub fn with_until(&self, until: NaiveDate) -> Option<Self> {
|
|
Self::new(self.from, until)
|
|
}
|
|
|
|
pub fn contains(&self, date: NaiveDate) -> bool {
|
|
self.from <= date && date <= self.until
|
|
}
|
|
|
|
pub fn from(&self) -> NaiveDate {
|
|
self.from
|
|
}
|
|
|
|
pub fn until(&self) -> NaiveDate {
|
|
self.until
|
|
}
|
|
|
|
pub fn years(&self) -> RangeInclusive<i32> {
|
|
self.from.year()..=self.until.year()
|
|
}
|
|
|
|
/// Expand the range so that it contains at least all dates from which the
|
|
/// original range could be reached using `delta`. This new range will
|
|
/// always contain the old range.
|
|
pub fn expand_by(&self, delta: &Delta) -> Self {
|
|
let expand_lower = cmp::min(-delta.upper_bound(), 0);
|
|
let expand_upper = cmp::max(-delta.lower_bound(), 0);
|
|
Self::new(
|
|
self.from + Duration::days(expand_lower.into()),
|
|
self.until + Duration::days(expand_upper.into()),
|
|
)
|
|
// The range is never shrunk, so the new range should always be valid.
|
|
.expect("expanded range shrunk")
|
|
}
|
|
|
|
/// Return a new range that contains at least all dates from which the
|
|
/// original range could be reached using `delta`. This new range might not
|
|
/// contain the old range.
|
|
pub fn move_by(&self, delta: &Delta) -> Self {
|
|
let move_lower = -delta.upper_bound();
|
|
let move_upper = -delta.lower_bound();
|
|
Self::new(
|
|
self.from + Duration::days(move_lower.into()),
|
|
self.until + Duration::days(move_upper.into()),
|
|
)
|
|
// The delta's upper bound is greater or equal than its lower bound, so
|
|
// the range should never become smaller. It can only move and expand.
|
|
.expect("moved range shrunk")
|
|
}
|
|
}
|