Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_datime/src/constant/month_of_year.rs

6.8 KiB, 25 runs

created by r1870400018:6341, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! Months of the year, numbered January 1 through December 12.
2//!
3//! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\
4//! Anthropic Claude
5
6use oxedyne_fe2o3_core::prelude::*;
7
8use std::fmt::{self, Display};
9
10#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
11pub enum MonthOfYear {
12 January,
13 February,
14 March,
15 April,
16 May,
17 June,
18 July,
19 August,
20 September,
21 October,
22 November,
23 December,
24}
25
26impl MonthOfYear {
27 /// January is 1 and December 12.
28 pub fn of(&self) -> u8 {
29 match self {
30 Self::January => 1,
31 Self::February => 2,
32 Self::March => 3,
33 Self::April => 4,
34 Self::May => 5,
35 Self::June => 6,
36 Self::July => 7,
37 Self::August => 8,
38 Self::September => 9,
39 Self::October => 10,
40 Self::November => 11,
41 Self::December => 12,
42 }
43 }
44
45 pub fn from_number(n: u8) -> Outcome<Self> {
46 match n {
47 1 => Ok(Self::January),
48 2 => Ok(Self::February),
49 3 => Ok(Self::March),
50 4 => Ok(Self::April),
51 5 => Ok(Self::May),
52 6 => Ok(Self::June),
53 7 => Ok(Self::July),
54 8 => Ok(Self::August),
55 9 => Ok(Self::September),
56 10 => Ok(Self::October),
57 11 => Ok(Self::November),
58 12 => Ok(Self::December),
59 _ => Err(err!(
60 "Invalid month number: {}, must be 1-12", n;
61 Invalid, Input, Range)),
62 }
63 }
64
65 pub fn next(&self) -> Self {
66 match self {
67 Self::January => Self::February,
68 Self::February => Self::March,
69 Self::March => Self::April,
70 Self::April => Self::May,
71 Self::May => Self::June,
72 Self::June => Self::July,
73 Self::July => Self::August,
74 Self::August => Self::September,
75 Self::September => Self::October,
76 Self::October => Self::November,
77 Self::November => Self::December,
78 Self::December => Self::January,
79 }
80 }
81
82 pub fn previous(&self) -> Self {
83 match self {
84 Self::January => Self::December,
85 Self::February => Self::January,
86 Self::March => Self::February,
87 Self::April => Self::March,
88 Self::May => Self::April,
89 Self::June => Self::May,
90 Self::July => Self::June,
91 Self::August => Self::July,
92 Self::September => Self::August,
93 Self::October => Self::September,
94 Self::November => Self::October,
95 Self::December => Self::November,
96 }
97 }
98
99 pub fn abbrev(&self) -> &'static str {
100 match self {
101 Self::January => "Jan",
102 Self::February => "Feb",
103 Self::March => "Mar",
104 Self::April => "Apr",
105 Self::May => "May",
106 Self::June => "Jun",
107 Self::July => "Jul",
108 Self::August => "Aug",
109 Self::September => "Sep",
110 Self::October => "Oct",
111 Self::November => "Nov",
112 Self::December => "Dec",
113 }
114 }
115
116 pub fn name(&self) -> &'static str {
117 match self {
118 Self::January => "January",
119 Self::February => "February",
120 Self::March => "March",
121 Self::April => "April",
122 Self::May => "May",
123 Self::June => "June",
124 Self::July => "July",
125 Self::August => "August",
126 Self::September => "September",
127 Self::October => "October",
128 Self::November => "November",
129 Self::December => "December",
130 }
131 }
132
133 /// February follows the Gregorian leap year rule.
134 pub fn days_in_month(&self, year: i32) -> u8 {
135 match self {
136 Self::January => 31,
137 Self::February => {
138 // Use default Gregorian calendar for leap year calculation
139 let calendar = crate::calendar::Calendar::new();
140 if calendar.is_leap_year(year) { 29 } else { 28 }
141 },
142 Self::March => 31,
143 Self::April => 30,
144 Self::May => 31,
145 Self::June => 30,
146 Self::July => 31,
147 Self::August => 31,
148 Self::September => 30,
149 Self::October => 31,
150 Self::November => 30,
151 Self::December => 31,
152 }
153 }
154
155 pub fn quarter(&self) -> u8 {
156 match self {
157 Self::January | Self::February | Self::March => 1,
158 Self::April | Self::May | Self::June => 2,
159 Self::July | Self::August | Self::September => 3,
160 Self::October | Self::November | Self::December => 4,
161 }
162 }
163
164 pub fn short_name(&self) -> &'static str {
165 self.abbrev()
166 }
167
168 pub fn long_name(&self) -> &'static str {
169 self.name()
170 }
171
172 /// Matches full names and abbreviations, case insensitively.
173 pub fn from_name(name: &str) -> Option<Self> {
174 let name = name.to_lowercase();
175 match name.as_str() {
176 "january" | "jan" => Some(Self::January),
177 "february" | "feb" => Some(Self::February),
178 "march" | "mar" => Some(Self::March),
179 "april" | "apr" => Some(Self::April),
180 "may" => Some(Self::May),
181 "june" | "jun" => Some(Self::June),
182 "july" | "jul" => Some(Self::July),
183 "august" | "aug" => Some(Self::August),
184 "september" | "sep" | "sept" => Some(Self::September),
185 "october" | "oct" => Some(Self::October),
186 "november" | "nov" => Some(Self::November),
187 "december" | "dec" => Some(Self::December),
188 _ => None,
189 }
190 }
191}
192
193impl Display for MonthOfYear {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(f, "{}", self.name())
196 }
197}
198
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn test_month_days_in_leap_year() {
206 // Test February in leap years and non-leap years
207 assert_eq!(MonthOfYear::February.days_in_month(2024), 29); // Leap year
208 assert_eq!(MonthOfYear::February.days_in_month(2023), 28); // Non-leap year
209 assert_eq!(MonthOfYear::February.days_in_month(2000), 29); // Leap year (divisible by 400)
210 assert_eq!(MonthOfYear::February.days_in_month(1900), 28); // Non-leap year (divisible by 100 but not 400)
211
212 // Test other months are unaffected by leap years
213 assert_eq!(MonthOfYear::January.days_in_month(2024), 31);
214 assert_eq!(MonthOfYear::January.days_in_month(2023), 31);
215 assert_eq!(MonthOfYear::March.days_in_month(2024), 31);
216 assert_eq!(MonthOfYear::April.days_in_month(2024), 30);
217 }
218}