Oregami
Repositories/oxedyne/fe2o3

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

10.1 KiB, 30 runs

created by r1870400018:6343, 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//! English ordinal numbers, first through thirty-first.
2//!
3//! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\
4//! Anthropic Claude
5
6use oxedyne_fe2o3_core::prelude::*;
7
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub enum OrdinalEnglish {
10 First,
11 Second,
12 Third,
13 Fourth,
14 Fifth,
15 Sixth,
16 Seventh,
17 Eighth,
18 Ninth,
19 Tenth,
20 Eleventh,
21 Twelfth,
22 Thirteenth,
23 Fourteenth,
24 Fifteenth,
25 Sixteenth,
26 Seventeenth,
27 Eighteenth,
28 Nineteenth,
29 Twentieth,
30 TwentyFirst,
31 TwentySecond,
32 TwentyThird,
33 TwentyFourth,
34 TwentyFifth,
35 TwentySixth,
36 TwentySeventh,
37 TwentyEighth,
38 TwentyNinth,
39 Thirtieth,
40 ThirtyFirst,
41}
42
43impl OrdinalEnglish {
44 pub fn from_number(n: u8) -> Outcome<Self> {
45 match n {
46 1 => Ok(Self::First),
47 2 => Ok(Self::Second),
48 3 => Ok(Self::Third),
49 4 => Ok(Self::Fourth),
50 5 => Ok(Self::Fifth),
51 6 => Ok(Self::Sixth),
52 7 => Ok(Self::Seventh),
53 8 => Ok(Self::Eighth),
54 9 => Ok(Self::Ninth),
55 10 => Ok(Self::Tenth),
56 11 => Ok(Self::Eleventh),
57 12 => Ok(Self::Twelfth),
58 13 => Ok(Self::Thirteenth),
59 14 => Ok(Self::Fourteenth),
60 15 => Ok(Self::Fifteenth),
61 16 => Ok(Self::Sixteenth),
62 17 => Ok(Self::Seventeenth),
63 18 => Ok(Self::Eighteenth),
64 19 => Ok(Self::Nineteenth),
65 20 => Ok(Self::Twentieth),
66 21 => Ok(Self::TwentyFirst),
67 22 => Ok(Self::TwentySecond),
68 23 => Ok(Self::TwentyThird),
69 24 => Ok(Self::TwentyFourth),
70 25 => Ok(Self::TwentyFifth),
71 26 => Ok(Self::TwentySixth),
72 27 => Ok(Self::TwentySeventh),
73 28 => Ok(Self::TwentyEighth),
74 29 => Ok(Self::TwentyNinth),
75 30 => Ok(Self::Thirtieth),
76 31 => Ok(Self::ThirtyFirst),
77 _ => Err(err!("Ordinal {} not implemented", n; Unimplemented)),
78 }
79 }
80
81 pub fn value(&self) -> u8 {
82 match self {
83 Self::First => 1,
84 Self::Second => 2,
85 Self::Third => 3,
86 Self::Fourth => 4,
87 Self::Fifth => 5,
88 Self::Sixth => 6,
89 Self::Seventh => 7,
90 Self::Eighth => 8,
91 Self::Ninth => 9,
92 Self::Tenth => 10,
93 Self::Eleventh => 11,
94 Self::Twelfth => 12,
95 Self::Thirteenth => 13,
96 Self::Fourteenth => 14,
97 Self::Fifteenth => 15,
98 Self::Sixteenth => 16,
99 Self::Seventeenth => 17,
100 Self::Eighteenth => 18,
101 Self::Nineteenth => 19,
102 Self::Twentieth => 20,
103 Self::TwentyFirst => 21,
104 Self::TwentySecond => 22,
105 Self::TwentyThird => 23,
106 Self::TwentyFourth => 24,
107 Self::TwentyFifth => 25,
108 Self::TwentySixth => 26,
109 Self::TwentySeventh => 27,
110 Self::TwentyEighth => 28,
111 Self::TwentyNinth => 29,
112 Self::Thirtieth => 30,
113 Self::ThirtyFirst => 31,
114 }
115 }
116
117 /// Accepts words and numeric forms alike, case insensitively.
118 pub fn from_name(name: &str) -> Option<Self> {
119 let name = name.to_lowercase();
120
121 // Handle numeric ordinals with suffixes
122 if let Some(ordinal) = Self::parse_numeric_ordinal(&name) {
123 return Some(ordinal);
124 }
125
126 // Handle word ordinals
127 match name.as_str() {
128 "first" => Some(Self::First),
129 "second" => Some(Self::Second),
130 "third" => Some(Self::Third),
131 "fourth" => Some(Self::Fourth),
132 "fifth" => Some(Self::Fifth),
133 "sixth" => Some(Self::Sixth),
134 "seventh" => Some(Self::Seventh),
135 "eighth" => Some(Self::Eighth),
136 "ninth" => Some(Self::Ninth),
137 "tenth" => Some(Self::Tenth),
138 "eleventh" => Some(Self::Eleventh),
139 "twelfth" => Some(Self::Twelfth),
140 "thirteenth" => Some(Self::Thirteenth),
141 "fourteenth" => Some(Self::Fourteenth),
142 "fifteenth" => Some(Self::Fifteenth),
143 "sixteenth" => Some(Self::Sixteenth),
144 "seventeenth" => Some(Self::Seventeenth),
145 "eighteenth" => Some(Self::Eighteenth),
146 "nineteenth" => Some(Self::Nineteenth),
147 "twentieth" => Some(Self::Twentieth),
148 "twenty-first" | "twenty first" => Some(Self::TwentyFirst),
149 "twenty-second" | "twenty second" => Some(Self::TwentySecond),
150 "twenty-third" | "twenty third" => Some(Self::TwentyThird),
151 "twenty-fourth" | "twenty fourth" => Some(Self::TwentyFourth),
152 "twenty-fifth" | "twenty fifth" => Some(Self::TwentyFifth),
153 "twenty-sixth" | "twenty sixth" => Some(Self::TwentySixth),
154 "twenty-seventh" | "twenty seventh" => Some(Self::TwentySeventh),
155 "twenty-eighth" | "twenty eighth" => Some(Self::TwentyEighth),
156 "twenty-ninth" | "twenty ninth" => Some(Self::TwentyNinth),
157 "thirtieth" => Some(Self::Thirtieth),
158 "thirty-first" | "thirty first" => Some(Self::ThirtyFirst),
159 _ => None,
160 }
161 }
162
163 /// Accepts "st", "nd", "rd" and "th" suffixes only.
164 fn parse_numeric_ordinal(name: &str) -> Option<Self> {
165 if name.len() < 3 {
166 return None;
167 }
168
169 let (num_part, suffix) = name.split_at(name.len() - 2);
170
171 // Check if it ends with valid ordinal suffix
172 let is_valid_suffix = match suffix {
173 "st" | "nd" | "rd" | "th" => true,
174 _ => false,
175 };
176
177 if !is_valid_suffix {
178 return None;
179 }
180
181 // Parse the numeric part
182 if let Ok(num) = num_part.parse::<u8>() {
183 Self::from_number(num).ok()
184 } else {
185 None
186 }
187 }
188
189 /// Upper case, matching the Java original.
190 pub fn to_long_name(&self) -> &'static str {
191 match self {
192 Self::First => "FIRST",
193 Self::Second => "SECOND",
194 Self::Third => "THIRD",
195 Self::Fourth => "FOURTH",
196 Self::Fifth => "FIFTH",
197 Self::Sixth => "SIXTH",
198 Self::Seventh => "SEVENTH",
199 Self::Eighth => "EIGHTH",
200 Self::Ninth => "NINTH",
201 Self::Tenth => "TENTH",
202 Self::Eleventh => "ELEVENTH",
203 Self::Twelfth => "TWELFTH",
204 Self::Thirteenth => "THIRTEENTH",
205 Self::Fourteenth => "FOURTEENTH",
206 Self::Fifteenth => "FIFTEENTH",
207 Self::Sixteenth => "SIXTEENTH",
208 Self::Seventeenth => "SEVENTEENTH",
209 Self::Eighteenth => "EIGHTEENTH",
210 Self::Nineteenth => "NINETEENTH",
211 Self::Twentieth => "TWENTIETH",
212 Self::TwentyFirst => "TWENTYFIRST",
213 Self::TwentySecond => "TWENTYSECOND",
214 Self::TwentyThird => "TWENTYTHIRD",
215 Self::TwentyFourth => "TWENTYFOURTH",
216 Self::TwentyFifth => "TWENTYFIFTH",
217 Self::TwentySixth => "TWENTYSIXTH",
218 Self::TwentySeventh => "TWENTYSEVENTH",
219 Self::TwentyEighth => "TWENTYEIGHTH",
220 Self::TwentyNinth => "TWENTYNINTH",
221 Self::Thirtieth => "THIRTIETH",
222 Self::ThirtyFirst => "THIRTYFIRST",
223 }
224 }
225
226 pub fn to_short_name(&self) -> String {
227 let num = self.value();
228 let suffix = match num {
229 1 | 21 | 31 => "ST",
230 2 | 22 => "ND",
231 3 | 23 => "RD",
232 _ => "TH",
233 };
234 format!("{}{}", num, suffix)
235 }
236
237 // Java-compatible aliases, carried over from the CalClock port.
238 pub fn of(&self) -> u8 {
239 self.value()
240 }
241
242 pub fn get(val: u8) -> Option<Self> {
243 Self::from_number(val).ok()
244 }
245
246 pub fn get_using_short_name(name: &str) -> Option<Self> {
247 let name = name.replace(" ", "").to_uppercase();
248 Self::parse_numeric_ordinal(&name.to_lowercase())
249 }
250
251 pub fn get_using_long_name(name: &str) -> Option<Self> {
252 let name = name.replace(" ", "").to_uppercase();
253 match name.as_str() {
254 "FIRST" => Some(Self::First),
255 "SECOND" => Some(Self::Second),
256 "THIRD" => Some(Self::Third),
257 "FOURTH" => Some(Self::Fourth),
258 "FIFTH" => Some(Self::Fifth),
259 "SIXTH" => Some(Self::Sixth),
260 "SEVENTH" => Some(Self::Seventh),
261 "EIGHTH" => Some(Self::Eighth),
262 "NINTH" => Some(Self::Ninth),
263 "TENTH" => Some(Self::Tenth),
264 "ELEVENTH" => Some(Self::Eleventh),
265 "TWELFTH" => Some(Self::Twelfth),
266 "THIRTEENTH" => Some(Self::Thirteenth),
267 "FOURTEENTH" => Some(Self::Fourteenth),
268 "FIFTEENTH" => Some(Self::Fifteenth),
269 "SIXTEENTH" => Some(Self::Sixteenth),
270 "SEVENTEENTH" => Some(Self::Seventeenth),
271 "EIGHTEENTH" => Some(Self::Eighteenth),
272 "NINETEENTH" => Some(Self::Nineteenth),
273 "TWENTIETH" => Some(Self::Twentieth),
274 "TWENTYFIRST" => Some(Self::TwentyFirst),
275 "TWENTYSECOND" => Some(Self::TwentySecond),
276 "TWENTYTHIRD" => Some(Self::TwentyThird),
277 "TWENTYFOURTH" => Some(Self::TwentyFourth),
278 "TWENTYFIFTH" => Some(Self::TwentyFifth),
279 "TWENTYSIXTH" => Some(Self::TwentySixth),
280 "TWENTYSEVENTH" => Some(Self::TwentySeventh),
281 "TWENTYEIGHTH" => Some(Self::TwentyEighth),
282 "TWENTYNINTH" => Some(Self::TwentyNinth),
283 "THIRTIETH" => Some(Self::Thirtieth),
284 "THIRTYFIRST" => Some(Self::ThirtyFirst),
285 _ => None,
286 }
287 }
288
289 pub fn get_using_name(name: &str) -> Option<Self> {
290 Self::get_using_short_name(name)
291 .or_else(|| Self::get_using_long_name(name))
292 }
293
294 pub fn is_ordinal_suffix(s: &str) -> bool {
295 let s = s.to_uppercase();
296 matches!(s.as_str(), "ST" | "ND" | "RD" | "TH")
297 }
298}