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 | |
| 6 | use oxedyne_fe2o3_core::prelude::*; |
| 7 | |
| 8 | use std::fmt::{self, Display}; |
| 9 | |
| 10 | #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] |
| 11 | pub 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 | |
| 26 | impl 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 | |
| 193 | impl 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)] |
| 201 | mod 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 | } |