1use std::str::Utf8Error;
3
4#[derive(Debug)]
5pub enum ParseError {
6 Invalid,
7 Utf8(Utf8Error),
8}
9
10#[derive(Debug)]
11pub enum FormatError {
12 TooLarge,
13 Utf8(Utf8Error),
14}
15
16pub enum Aura {
17 T,
19 Ta,
21 Tas,
23 U,
25 Ud,
27 Ux,
29 Uv,
31 Uw,
33 Da,
35 Dr,
37}
38
39pub mod date {
40 use std::str::FromStr;
41
42 use crate::sept::ParseError;
43
44 #[derive(Debug)]
45 struct Dat {
46 pos: bool,
47 year: u64,
48 month: u64,
49 time: Tarp,
50 }
51
52 #[derive(Debug, PartialEq)]
53 struct Tarp {
54 day: u64,
55 hour: u64,
56 minute: u64,
57 second: u64,
58 ms: Vec<u64>,
59 }
60
61 const DA_UNIX_EPOCH: u128 = 170141184475152167957503069145530368000; const DA_SECOND: u128 = 18446744073709551616; const EPOCH: u64 = 292277024400;
64
65 const MOH_YO: [u64; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
66 const MOY_YO: [u64; 12] = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
67 const DAY_YO: u64 = 86400;
68 const HOR_YO: u64 = 3600;
69 const MIT_YO: u64 = 60;
70 const ERA_YO: u64 = 146097;
71 const CET_YO: u64 = 36524;
72
73 fn is_leap_year(year: u64) -> bool {
74 (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
75 }
76
77 fn year(det: &Dat) -> u128 {
78 let yer = if det.pos {
79 EPOCH + det.year
80 } else {
81 EPOCH - (det.year - 1)
82 };
83
84 let day = {
85 let cah = if is_leap_year(yer) {
86 MOY_YO.to_vec()
87 } else {
88 MOH_YO.to_vec()
89 };
90 let mut d = det.time.day - 1;
91 let mut m = det.month - 1;
92 let mut idx = 0;
93 while m != 0 {
94 d += cah[idx];
95 m -= 1;
96 idx += 1;
97 }
98
99 let mut loop_continue = true;
100 let mut y = yer;
101
102 while loop_continue {
103 if y % 4 != 0 {
104 y -= 1;
105 d += if is_leap_year(y) { 366 } else { 365 };
106 } else if y % 100 != 0 {
107 y -= 4;
108 d += if is_leap_year(y) { 1461 } else { 1460 };
109 } else if y % 400 != 0 {
110 y -= 100;
111 d += if is_leap_year(y) { 36525 } else { 36524 };
112 } else {
113 let eras = y / 400;
114 d += eras * (4 * 36524 + 1);
115 loop_continue = false;
116 }
117 }
118 d
119 };
120
121 let sec = det.time.second as u128
122 + (DAY_YO as u128 * day as u128)
123 + (HOR_YO as u128 * det.time.hour as u128)
124 + (MIT_YO as u128 * det.time.minute as u128);
125
126 let mut fac: u128 = 0;
127 let mut muc = 3;
128
129 for &ms in &det.time.ms {
130 fac += (ms as u128) << (16 * muc);
131 muc -= 1;
132 }
133
134 fac | (sec << 64)
135 }
136
137 pub fn parse_da(x: &str) -> Result<u128, ParseError> {
138 let parts: Vec<&str> = x.split("..").collect();
139 let date_parts: Vec<&str> = parts[0][1..].split('.').collect();
140 let time_parts: Vec<&str> = parts[1].split('.').collect();
141 let ms_parts: Vec<&str> = parts[2].split('.').collect();
142
143 let millis: Vec<u64> = ms_parts
144 .iter()
145 .map(|m| u64::from_str_radix(m, 16).map_err(|e| ParseError::Invalid))
146 .collect::<Result<Vec<u64>, _>>()?;
147
148 fn parse<F: FromStr>(s: &str) -> Result<F, ParseError> {
149 F::from_str(s).map_err(|_e| ParseError::Invalid)
150 }
151
152 Ok(year(&Dat {
153 pos: true,
154 year: parse(date_parts[0])?,
155 month: parse(date_parts[1])?,
156 time: Tarp {
157 day: parse(date_parts[2])?,
158 hour: parse(time_parts[0])?,
159 minute: parse(time_parts[1])?,
160 second: parse(time_parts[2])?,
161 ms: millis,
162 },
163 }))
164 }
165 fn yell(x: u128) -> Tarp {
166 let sec = x >> 64;
167 let raw = x & ((1 << 64) - 1); let mut ms = Vec::new();
171 let mut muc = 4;
172 let mut current_raw = raw;
173
174 while current_raw != 0 && muc > 0 {
175 muc -= 1;
176 let value = (current_raw >> (muc * 16)) & 0xFFFF;
178 if value != 0 {
179 ms.push(value as u64);
180 }
181 current_raw &= (1 << (muc * 16)) - 1;
183 }
184
185 let day = sec / DAY_YO as u128;
186 let mut sec = sec % DAY_YO as u128;
187 let hor = sec / HOR_YO as u128;
188 sec %= HOR_YO as u128;
189 let mit = sec / MIT_YO as u128;
190 sec %= MIT_YO as u128;
191
192 Tarp {
193 ms,
194 day: day as u64,
195 minute: mit as u64,
196 hour: hor as u64,
197 second: sec as u64,
198 }
199 }
200
201 fn yall(mut day: u64) -> (u64, u64, u64) {
202 let era = day / ERA_YO;
203 day %= ERA_YO;
204
205 let (cet, mut lep) = if day < (CET_YO + 1) {
206 (0, true)
207 } else {
208 let mut cet = 1;
209 day -= CET_YO + 1;
210 cet += day / CET_YO;
211 day %= CET_YO;
212 (cet, false)
213 };
214
215 let mut yer = (era * 400) + (cet * 100);
216 let mut loop_continue = true;
217
218 while loop_continue {
219 let dis = if lep { 366 } else { 365 };
220 if day >= dis {
221 yer += 1;
222 day -= dis;
223 lep = yer % 4 == 0;
224 } else {
225 loop_continue = false;
226 let mut mot = 0;
227 let cah = if lep { &MOY_YO } else { &MOH_YO };
228
229 while mot < 12 {
230 let zis = cah[mot as usize];
231 if day < zis {
232 return (yer, mot + 1, day + 1);
233 }
234 mot += 1;
235 day -= zis;
236 }
237 }
238 }
239
240 (0, 0, 0)
241 }
242
243 fn yore(x: u128) -> Dat {
244 let time = yell(x);
245 let (y, month, d) = yall(time.day);
246 let pos = y > EPOCH;
247 let year = if pos { y - EPOCH } else { EPOCH + 1 - y };
248
249 Dat {
250 pos,
251 year,
252 month,
253 time: Tarp { day: d, ..time },
254 }
255 }
256
257 fn format_ms(ms: &[u64]) -> String {
258 let foo = ms
259 .iter()
260 .rev()
261 .skip_while(|x| **x == 0)
262 .collect::<Vec<&u64>>();
263 let ms_part = foo
264 .iter()
265 .rev()
266 .map(|x| format!("{:04x}", x))
267 .collect::<Vec<String>>()
268 .join(".");
269 ms_part
270 }
271
272 pub fn format_da(x: u128) -> String {
273 let dat = yore(x);
274 let ms_part = format_ms(&dat.time.ms);
275
276 format!(
277 "~{}.{}.{}..{}.{}.{}..{}",
278 dat.year,
279 dat.month,
280 dat.time.day,
281 dat.time.hour,
282 dat.time.minute,
283 dat.time.second,
284 ms_part
285 )
286 }
287
288 pub fn format_date(x: u128) -> String {
289 let dat = yore(x);
290 format!("~{}.{}.{}", dat.year, dat.month, dat.time.day)
291 }
292
293 pub fn format_time(x: u128) -> String {
294 let dat = yore(x);
295 format!(
296 "~{}.{}.{}..{}.{}.{}",
297 dat.year, dat.month, dat.time.day, dat.time.hour, dat.time.minute, dat.time.second
298 )
299 }
300
301 pub fn da_to_unix(da: u128) -> u64 {
302 let offset = DA_SECOND / 2000;
303 let epoch_adjusted = offset + (da - DA_UNIX_EPOCH);
304
305 ((epoch_adjusted * 1000 / DA_SECOND) as f64).round() as u64
306 }
307
308 pub fn unix_to_da(unix: u64) -> u128 {
309 let time_since_epoch = (unix as u128) * DA_SECOND / 1000;
310 DA_UNIX_EPOCH + time_since_epoch
311 }
312
313 pub fn get_time() -> u128 {
314 let now = std::time::SystemTime::now();
315 let since_the_epoch = now.duration_since(std::time::UNIX_EPOCH).unwrap();
316
317 unix_to_da(since_the_epoch.as_millis() as u64)
318 }
319
320 #[cfg(test)]
321 mod tests {
322 use super::*;
323
324 #[test]
325 fn test_format_da() {
326 let word = 170141184507102559553699322435033104384u128;
327 let str = format_da(word);
328 let tarp = yell(word);
329 let expected = Tarp {
330 ms: vec![1175],
331 day: 106751991823991,
332 hour: 16,
333 minute: 36,
334 second: 39,
335 };
336 assert_eq!(tarp, expected);
337 }
338
339 #[test]
340 fn test_parse_da() {
341 let word = 170141184507102559553699322435033104384u128;
342 let str = "~2024.11.19..16.36.39..0497";
343 let da = parse_da(str).unwrap();
344 assert_eq!(da, word);
345 }
346 }
347}