summaryrefslogtreecommitdiff
path: root/src/date.rs
diff options
context:
space:
mode:
authorBotahamec <botahamec@outlook.com>2022-03-16 14:51:49 -0400
committerBotahamec <botahamec@outlook.com>2022-03-16 14:51:49 -0400
commit5ca69f1830763b689bae9c4873a2912b3f1e23b1 (patch)
tree86d4e9c5cf3a79ae372509a28e962c200fa094f5 /src/date.rs
parent0fb870509821eb6f8158a9ee3cc02e6a0f951c86 (diff)
Crude add year and add month
Diffstat (limited to 'src/date.rs')
-rw-r--r--src/date.rs58
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);