klirr_core/models/
month.rs1use crate::prelude::*;
2
3#[derive(
5 Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Display, Serialize, Deserialize, IsVariant,
6)]
7#[display("{}", self.month())]
8pub enum Month {
9 January = 1,
10 February,
11 March,
12 April,
13 May,
14 June,
15 July,
16 August,
17 September,
18 October,
19 November,
20 December,
21}
22
23impl std::fmt::Debug for Month {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", self.month())
26 }
27}
28
29impl Month {
30 pub fn month(&self) -> &u8 {
40 match self {
41 Month::January => &1,
42 Month::February => &2,
43 Month::March => &3,
44 Month::April => &4,
45 Month::May => &5,
46 Month::June => &6,
47 Month::July => &7,
48 Month::August => &8,
49 Month::September => &9,
50 Month::October => &10,
51 Month::November => &11,
52 Month::December => &12,
53 }
54 }
55}
56impl std::ops::Deref for Month {
57 type Target = u8;
58 fn deref(&self) -> &Self::Target {
59 self.month()
60 }
61}
62
63impl TryFrom<i32> for Month {
64 type Error = crate::prelude::Error;
65
66 fn try_from(month: i32) -> Result<Self> {
78 match month {
79 1 => Ok(Month::January),
80 2 => Ok(Month::February),
81 3 => Ok(Month::March),
82 4 => Ok(Month::April),
83 5 => Ok(Month::May),
84 6 => Ok(Month::June),
85 7 => Ok(Month::July),
86 8 => Ok(Month::August),
87 9 => Ok(Month::September),
88 10 => Ok(Month::October),
89 11 => Ok(Month::November),
90 12 => Ok(Month::December),
91 _ => Err(Error::InvalidMonth {
92 month,
93 reason: "Month must be between 1 and 12".to_string(),
94 }),
95 }
96 }
97}
98
99impl FromStr for Month {
100 type Err = crate::prelude::Error;
101
102 fn from_str(s: &str) -> Result<Self> {
114 let month = s.parse::<i32>().map_err(|_| Error::FailedToParseMonth {
115 invalid_string: s.to_owned(),
116 })?;
117 Self::try_from(month)
118 }
119}
120
121impl TryFrom<u8> for Month {
122 type Error = crate::prelude::Error;
123 fn try_from(month: u8) -> Result<Self> {
124 Self::try_from(month as i32)
125 }
126}
127
128impl TryFrom<u32> for Month {
129 type Error = crate::prelude::Error;
130 fn try_from(month: u32) -> Result<Self> {
131 Self::try_from(month as i32)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138 use insta::assert_debug_snapshot;
139 use test_log::test;
140
141 #[test]
142 fn test_month_conversion() {
143 assert_eq!(Month::try_from(1).unwrap(), Month::January);
144 assert_eq!(Month::try_from(2).unwrap(), Month::February);
145 assert_eq!(Month::try_from(7).unwrap(), Month::July);
146 assert_eq!(Month::try_from(8).unwrap(), Month::August);
147 assert_eq!(Month::try_from(9).unwrap(), Month::September);
148 assert_eq!(Month::try_from(10).unwrap(), Month::October);
149 assert_eq!(Month::try_from(11).unwrap(), Month::November);
150 assert_eq!(Month::try_from(12).unwrap(), Month::December);
151 assert!(Month::try_from(0).is_err());
152 assert!(Month::try_from(13).is_err());
153 }
154
155 #[test]
156 fn test_month_display() {
157 assert_eq!(Month::January.to_string(), "1");
158 assert_eq!(Month::December.to_string(), "12");
159 }
160
161 #[test]
162 fn test_month_deref() {
163 let month: &u8 = &Month::March;
164 assert_eq!(*month, 3);
165 }
166
167 #[test]
168 fn test_month_debug() {
169 assert_debug_snapshot!(Month::April, @"4");
170 }
171
172 #[test]
173 fn test_from_str_invalid_all_reasons() {
174 let invalid_months = ["0", "13", "abc", "1.5"];
175 for &invalid in &invalid_months {
176 let result: Result<Month> = invalid.parse();
177 assert!(
178 result.is_err(),
179 "Expected error for invalid month '{}'",
180 invalid
181 );
182 }
183 }
184}