baseunits_rs/time/
month_of_year.rs1use 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}