diff options
| author | Botahamec <botahamec@outlook.com> | 2022-03-16 14:51:49 -0400 |
|---|---|---|
| committer | Botahamec <botahamec@outlook.com> | 2022-03-16 14:51:49 -0400 |
| commit | 5ca69f1830763b689bae9c4873a2912b3f1e23b1 (patch) | |
| tree | 86d4e9c5cf3a79ae372509a28e962c200fa094f5 /src/date.rs | |
| parent | 0fb870509821eb6f8158a9ee3cc02e6a0f951c86 (diff) | |
Crude add year and add month
Diffstat (limited to 'src/date.rs')
| -rw-r--r-- | src/date.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/date.rs b/src/date.rs index 194fd02..43355ab 100644 --- a/src/date.rs +++ b/src/date.rs @@ -3,6 +3,8 @@ use crate::{Month, Year}; use core::cmp::Ordering; use core::fmt::Display; +use thiserror::Error; + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct Date { year: Year, @@ -10,6 +12,26 @@ pub struct Date { day: u8, } +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)] +#[error("Tried to construct {given_day} {month}, but {month} only has {month_max_day} days")] +pub struct DayGreaterThanMaximumForMonthError { + month: Month, + given_day: u8, + month_max_day: u8, +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)] +#[error("Tried to construct a leap day in {0} which is not a leap year")] +pub struct LeapDayNotInLeapYearError(Year); + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)] +pub enum InvalidDateError { + #[error("{0}")] + DayTooBig(DayGreaterThanMaximumForMonthError), + #[error("{0}")] + NonLeapYear(LeapDayNotInLeapYearError), +} + impl Date { /// The earliest date which can be represented pub const MIN: Self = unsafe { Self::from_ymd_unchecked(Year::MIN, Month::January, 1) }; @@ -56,6 +78,42 @@ impl Date { self.year.is_leap_year() } + // TODO overflow handling + pub const fn add_years(self, years: i16) -> Result<Self, LeapDayNotInLeapYearError> { + let year = self.year + years; + + if self.day == 29 && self.month == Month::February && !year.is_leap_year() { + Err(LeapDayNotInLeapYearError(self.year)) + } else { + Ok(Self { + year, + month: self.month, + day: self.day, + }) + } + } + + // TODO overflow handling + pub const fn add_months(self, months: i8) -> Result<Self, DayGreaterThanMaximumForMonthError> { + let (month, years_to_add) = self.month.add_overflowing(months); + let year = self.year + years_to_add; + let max_days_for_month = month.days(year.is_leap_year()); + + if self.day > max_days_for_month { + Err(DayGreaterThanMaximumForMonthError { + month, + given_day: self.day, + month_max_day: max_days_for_month, + }) + } else { + Ok(Self { + year, + month, + day: self.day, + }) + } + } + // TODO handle BCE properly pub const fn days_after_common_era(self) -> isize { let year = self.year.wrapping_sub(1); |
