baseunits_rs/time/
month_of_year.rs

1use std::cmp::Ordering;
2use std::hash::{Hash, Hasher};
3
4use chrono::{Datelike, Utc};
5use num::ToPrimitive;
6use rust_decimal::prelude::FromPrimitive;
7
8use crate::time::{DayOfMonth, is_leap_year, Month, CalendarYearMonth};
9
10#[derive(Debug, Clone, Eq)]
11pub struct MonthOfYear {
12  last_day: DayOfMonth,
13  value: Month,
14}
15
16impl PartialEq for MonthOfYear {
17  fn eq(&self, other: &Self) -> bool {
18    self.value.eq(&other.value)
19  }
20}
21
22impl PartialOrd for MonthOfYear {
23  fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24    self.value.partial_cmp(&other.value)
25  }
26}
27
28impl Hash for MonthOfYear {
29  fn hash<H: Hasher>(&self, state: &mut H) {
30    self.value.hash(state);
31  }
32}
33
34impl MonthOfYear {
35  pub const JAN: MonthOfYear = MonthOfYear {
36    last_day: DayOfMonth(31),
37    value: Month::January,
38  };
39  pub const FEB: MonthOfYear = MonthOfYear {
40    last_day: DayOfMonth(28),
41    value: Month::February,
42  };
43  pub const MAR: MonthOfYear = MonthOfYear {
44    last_day: DayOfMonth(31),
45    value: Month::March,
46  };
47  pub const APR: MonthOfYear = MonthOfYear {
48    last_day: DayOfMonth(30),
49    value: Month::April,
50  };
51  pub const MAY: MonthOfYear = MonthOfYear {
52    last_day: DayOfMonth(31),
53    value: Month::May,
54  };
55  pub const JUN: MonthOfYear = MonthOfYear {
56    last_day: DayOfMonth(30),
57    value: Month::June,
58  };
59  pub const JUL: MonthOfYear = MonthOfYear {
60    last_day: DayOfMonth(31),
61    value: Month::July,
62  };
63  pub const AUG: MonthOfYear = MonthOfYear {
64    last_day: DayOfMonth(31),
65    value: Month::August,
66  };
67  pub const SEP: MonthOfYear = MonthOfYear {
68    last_day: DayOfMonth(30),
69    value: Month::September,
70  };
71  pub const OCT: MonthOfYear = MonthOfYear {
72    last_day: DayOfMonth(31),
73    value: Month::October,
74  };
75  pub const NOV: MonthOfYear = MonthOfYear {
76    last_day: DayOfMonth(30),
77    value: Month::November,
78  };
79  pub const DEC: MonthOfYear = MonthOfYear {
80    last_day: DayOfMonth(31),
81    value: Month::December,
82  };
83
84  pub fn new(last_day_of_this_month: DayOfMonth, calendar_value: Month) -> Self {
85    Self {
86      last_day: last_day_of_this_month,
87      value: calendar_value,
88    }
89  }
90
91  pub fn from_month(month: Month) -> Self {
92    [
93      MonthOfYear::JAN,
94      MonthOfYear::FEB,
95      MonthOfYear::MAR,
96      MonthOfYear::APR,
97      MonthOfYear::MAY,
98      MonthOfYear::JUN,
99      MonthOfYear::JUL,
100      MonthOfYear::AUG,
101      MonthOfYear::SEP,
102      MonthOfYear::OCT,
103      MonthOfYear::NOV,
104      MonthOfYear::DEC,
105    ]
106    .iter()
107    .find(|&e| e.value == month)
108    .unwrap()
109    .clone()
110  }
111
112  pub fn as_value(&self) -> &Month {
113    &self.value
114  }
115
116  pub const DAY_OF_MONTH_29: DayOfMonth = DayOfMonth(29);
117
118  pub fn as_last_day(&self) -> &DayOfMonth {
119    if self.value == Month::February && is_leap_year(Utc::today().year()) {
120      &MonthOfYear::DAY_OF_MONTH_29
121    } else {
122      &self.last_day
123    }
124  }
125
126  pub fn add_with_overflow(&self) -> (Self, bool) {
127    let month_num = self.value.to_i64().unwrap() + 1i64;
128    if month_num > Month::December.to_i64().unwrap() {
129      let m = Month::from_i64(month_num - Month::December.to_i64().unwrap()).unwrap();
130      (Self::from_month(m), true)
131    } else {
132      let m = Month::from_i64(month_num).unwrap();
133      (Self::from_month(m), false)
134    }
135  }
136
137  pub fn on(self, year: i32) -> CalendarYearMonth {
138    CalendarYearMonth::new(year, self)
139  }
140
141  pub fn is_after(&self, other: &Self) -> bool {
142    !self.is_before(other) && self != other
143  }
144
145  pub fn is_before(&self, other: &Self) -> bool {
146    self.value < other.value
147  }
148}
149
150#[cfg(test)]
151mod tests {
152  use crate::time::{MonthOfYear, Month, DayOfMonth};
153
154  #[test]
155  fn test_from_month() {
156    let moy = MonthOfYear::from_month(Month::January);
157    assert_eq!(moy.value, Month::January);
158    assert_eq!(moy.last_day, DayOfMonth::new(31))
159  }
160}