1use tokio::time::Sleep;
10
11pub static mut TIME_OFFSET: Option<i16> = None;
14
15const ONE_MILLISECOND: i64 = 1;
16const ONE_SECOND: i64 = 1000 * ONE_MILLISECOND;
17const ONE_MINUTE: i64 = 60 * ONE_SECOND;
18const ONE_HOUR: i64 = 60 * ONE_MINUTE;
19const ONE_DAY: i64 = 24 * ONE_HOUR;
20const ONE_WEEK: i64 = 7 * ONE_DAY;
21const ONE_YEAR: i64 = 365 * ONE_DAY;
23const FOUR_YEAR: i64 = 4 * ONE_YEAR + ONE_DAY;
24const ONE_HUNDRED_YEAR: i64 = 25 * FOUR_YEAR - ONE_DAY;
25const FOUR_HUNDRED_YEAR: i64 = 4 * ONE_HUNDRED_YEAR + ONE_DAY;
26const TIME_0: i64 =
27 4 * FOUR_HUNDRED_YEAR + 3 * ONE_HUNDRED_YEAR + ONE_DAY + 17 * FOUR_YEAR + 2 * ONE_YEAR;
28
29#[derive(Debug, Clone, PartialEq)]
36pub struct DateTime {
37 pub year: usize,
39 pub month: usize,
41 pub day: usize,
43 pub hour: usize,
45 pub minute: usize,
47 pub second: usize,
49 pub millisecond: usize,
51 pub day_of_year: usize,
53 pub weekday: usize,
55 pub timestamp: i64,
57 pub offset: i16,
59}
60
61impl DateTime {
62 pub fn new() -> Self {
68 return Self::from((Self::now(), None));
69 }
70
71 pub fn now() -> i64 {
73 #[cfg(target_os = "linux")]
74 unsafe {
75 use std::ffi::c_int;
85 use std::ffi::c_long;
86 #[derive(Debug, Clone, Default, PartialEq)]
87 #[repr(C)]
88 pub struct TimeValue {
89 pub tv_sec: c_long,
90 pub tv_usec: c_long,
91 }
92 #[derive(Debug, Clone, Default, PartialEq)]
93 #[repr(C)]
94 pub struct TimeZone {
95 pub tz_minuteswest: c_int,
96 pub tz_dsttime: c_int,
97 }
98 extern "C" {
99 fn gettimeofday(tv: *mut TimeValue, tz: *mut TimeZone) -> c_int;
100 }
101 let mut tv: TimeValue = Default::default();
102 let mut tz: TimeZone = Default::default();
103 if gettimeofday(&mut tv, &mut tz) != 0 {
104 return 0;
105 }
106 return tv.tv_sec as i64 * 1000 + tv.tv_usec as i64 / 1000;
107 }
108 #[cfg(target_os = "windows")]
109 unsafe {
110 use std::ffi::c_long;
125 use std::ffi::c_short;
126 #[allow(non_snake_case)]
127 #[derive(Debug, Clone, Default)]
128 #[repr(C)]
129 struct SYSTEMTIME {
130 wYear: c_short,
131 wMonth: c_short,
132 wDayOfWeek: c_short,
133 wDay: c_short,
134 wHour: c_short,
135 wMinute: c_short,
136 wSecond: c_short,
137 wMilliseconds: c_short,
138 }
139 extern "C" {
140 fn GetLocalTime(lpSystemTime: *mut SYSTEMTIME);
141 fn time(t: *mut c_long) -> c_long;
142 }
143 let mut st: SYSTEMTIME = Default::default();
144 GetLocalTime(&mut st);
145 let mut t: c_long = 0;
146 time(&mut t);
147 return t as i64 * 1000 + st.wMilliseconds as i64;
148 }
149 }
150
151 pub fn to_utc(&self) -> Self {
153 return Self::from((self.timestamp, Some(0)));
154 }
155}
156
157impl From<(i64, Option<i16>)> for DateTime {
158 fn from(value: (i64, Option<i16>)) -> Self {
164 let (timestamp_, offset) = value;
165 let offset: i16 = match offset {
166 Some(offset) => offset,
167 None => unsafe { *TIME_OFFSET.as_ref().unwrap() },
168 };
169 let offset_hour: i16 = offset / 100 % 100;
170 let offset_minute: i16 = offset % 100;
171 let mut timestamp: i64 = TIME_0
172 + offset_hour as i64 * 60 * 60 * 1000
173 + offset_minute as i64 * 60 * 1000
174 + timestamp_;
175 let mut year: i64 = 0;
177 year += timestamp / FOUR_HUNDRED_YEAR * 400;
178 timestamp %= FOUR_HUNDRED_YEAR;
179 if ONE_HUNDRED_YEAR + ONE_DAY <= timestamp {
180 timestamp -= ONE_HUNDRED_YEAR;
181 timestamp -= ONE_DAY;
182 year += 100;
183 if ONE_HUNDRED_YEAR <= timestamp {
184 timestamp -= ONE_HUNDRED_YEAR;
185 year += 100;
186 }
187 if ONE_HUNDRED_YEAR <= timestamp {
188 timestamp -= ONE_HUNDRED_YEAR;
189 year += 100;
190 }
191 }
192 if year % 400 != 0 && 4 * ONE_YEAR <= timestamp {
193 timestamp -= 4 * ONE_YEAR;
194 year += 4;
195 }
196 year += timestamp / FOUR_YEAR * 4;
197 timestamp %= FOUR_YEAR;
198 if ONE_YEAR + ONE_DAY <= timestamp {
199 timestamp -= ONE_YEAR;
200 timestamp -= ONE_DAY;
201 year += 1;
202 if ONE_YEAR <= timestamp {
203 timestamp -= ONE_YEAR;
204 year += 1;
205 }
206 if ONE_YEAR <= timestamp {
207 timestamp -= ONE_YEAR;
208 year += 1;
209 }
210 }
211 let day_of_year: i64 = timestamp / ONE_DAY + 1;
213 let mut month: i64 = 0;
216 for x in 1..=12 {
217 let max_days: i64 = match x {
218 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
219 2 => {
220 if year % 400 == 0 || year % 100 != 0 && year % 4 == 0 {
221 29
222 } else {
223 28
224 }
225 }
226 _ => 30,
227 };
228 if max_days * ONE_DAY <= timestamp {
229 timestamp -= max_days * ONE_DAY;
230 continue;
231 } else {
232 month = x;
233 break;
234 }
235 }
236 let day: i64 = 1 + timestamp / ONE_DAY;
239 timestamp %= ONE_DAY;
240 let hour: i64 = timestamp / ONE_HOUR;
243 timestamp %= ONE_HOUR;
244 let minute: i64 = timestamp / ONE_MINUTE;
245 timestamp %= ONE_MINUTE;
246 let second: i64 = timestamp / ONE_SECOND;
247 timestamp %= ONE_SECOND;
248 let millisecond: i64 = timestamp / ONE_MILLISECOND;
249 let mut weekday: i64 = (TIME_0
255 + offset_hour as i64 * 60 * 60 * 1000
256 + offset_minute as i64 * 60 * 1000
257 + timestamp_)
258 % ONE_WEEK
259 / ONE_DAY
260 + 1
261 + 5;
262 if 7 < weekday {
263 weekday -= 7;
264 }
265 return Self {
267 year: year as usize,
268 month: month as usize,
269 day: day as usize,
270 hour: hour as usize,
271 minute: minute as usize,
272 second: second as usize,
273 millisecond: millisecond as usize,
274 day_of_year: day_of_year as usize,
275 weekday: weekday as usize,
276 timestamp: timestamp_,
277 offset: offset,
278 };
279 }
280}
281
282impl From<(usize, usize, usize, usize, usize, usize, usize, Option<i16>)> for DateTime {
283 fn from(value: (usize, usize, usize, usize, usize, usize, usize, Option<i16>)) -> Self {
303 let (year, month, day, hour, minute, second, millisecond, offset) = value;
304 if month == 0 || 12 < month {
305 panic!("@month={:?}", month);
306 }
307 let max_days: usize = match month {
308 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
309 2 => {
310 if year % 400 == 0 || year % 100 != 0 && year % 4 == 0 {
311 29
312 } else {
313 28
314 }
315 }
316 _ => 30,
317 };
318 if day == 0 || max_days < day {
319 panic!("@day={:?}", day);
320 }
321 if 23 < hour {
322 panic!("@hour={:?}", hour);
323 }
324 if 59 < minute {
325 panic!("@minute={:?}", minute);
326 }
327 if 59 < second {
328 panic!("@second={:?}", second);
329 }
330 if 999 < millisecond {
331 panic!("@millisecond={:?}", millisecond);
332 }
333 let mut timestamp: i64 = 0;
334 let mut t: i64 = year as i64;
335 timestamp += t * ONE_YEAR;
337 timestamp += t / 400 * 97 * ONE_DAY;
338 t %= 400;
339 if t != 0 {
340 timestamp += (t / 100 * 24 + 1) * ONE_DAY;
341 t %= 100;
342 }
343 if t != 0 {
344 timestamp -= ONE_DAY;
345 if t % 4 != 0 {
346 timestamp += ONE_DAY;
347 }
348 timestamp += (t / 4) * ONE_DAY;
349 t %= 4;
350 }
351 let _ = t;
352 t = 0;
354 for x in 1..=12 {
355 if month <= x {
356 break;
357 }
358 let max_days: i64 = match x {
359 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
360 2 => {
361 if year % 400 == 0 || year % 100 != 0 && year % 4 == 0 {
362 29
363 } else {
364 28
365 }
366 }
367 _ => 30,
368 };
369 timestamp += max_days * ONE_DAY;
370 t += max_days;
371 }
372 timestamp += (day as i64 - 1) * ONE_DAY;
375 timestamp += hour as i64 * ONE_HOUR;
377 timestamp += minute as i64 * ONE_MINUTE;
378 timestamp += second as i64 * ONE_SECOND;
379 timestamp += millisecond as i64 * ONE_MILLISECOND;
380 let offset: i16 = match offset {
383 Some(offset) => offset,
384 None => unsafe { *TIME_OFFSET.as_ref().unwrap() },
385 };
386 let offset_hour: i16 = offset / 100 % 100;
387 let offset_minute: i16 = offset % 100;
388 timestamp -= TIME_0;
389 timestamp -= offset_hour as i64 * 60 * 60 * 1000;
390 timestamp -= offset_minute as i64 * 60 * 1000;
391 return Self::from((timestamp, Some(offset)));
392 }
411}
412
413impl ToString for DateTime {
414 fn to_string(&self) -> String {
416 let v1: String = format!(
417 "{}-{:02}-{:02}T{:02}:{:02}:{:02}.{}",
418 self.year,
419 self.month,
420 self.day,
421 self.hour,
422 self.minute,
423 self.second,
424 self.timestamp % 1000
425 );
426 let v2: &str = if self.offset == 0 {
427 ""
428 } else if self.offset < 0 {
429 "-"
430 } else {
431 "+"
432 };
433 let offset: i16 = if self.offset < 0 {
434 -self.offset
435 } else {
436 self.offset
437 };
438 let v3: String = if offset == 0 {
439 "Z".to_string()
440 } else {
441 format!("{:02}:{:02}", offset / 100 % 100, offset % 100)
442 };
443 let result: String = v1 + v2 + &v3;
444 let result: String = format!("{result:29}");
445 return result;
446 }
447}
448
449#[ctor::ctor]
452fn init() {
453 #[cfg(target_os = "linux")]
454 unsafe {
455 use std::ffi::c_long;
458 extern "C" {
459 static mut timezone: c_long;
460 fn tzset();
461 }
462 tzset();
463 let offset_hour: i16 = timezone as i16 / 60 / 60;
464 let offset_minute: i16 = timezone as i16 / 60 % 60;
465 TIME_OFFSET = Some(-(offset_hour * 100 + offset_minute));
466 }
467 #[cfg(target_os = "windows")]
468 unsafe {
469 use std::ffi::c_int;
492 use std::ffi::c_long;
493 use std::ffi::c_ushort;
494 #[allow(non_snake_case)]
495 #[derive(Debug, Clone, Default)]
496 #[repr(C)]
497 struct SYSTEMTIME {
498 wYear: c_ushort,
499 wMonth: c_ushort,
500 wDayOfWeek: c_ushort,
501 wDay: c_ushort,
502 wHour: c_ushort,
503 wMinute: c_ushort,
504 wSecond: c_ushort,
505 wMilliseconds: c_ushort,
506 }
507 #[allow(non_camel_case_types)]
508 #[allow(non_snake_case)]
509 #[derive(Debug, Clone, Default)]
510 #[repr(C)]
511 struct TIME_ZONE_INFORMATION {
512 Bias: c_long,
513 StandardName: [c_ushort; 32],
514 StandardDate: SYSTEMTIME,
515 StandardBias: c_long,
516 DaylightName: [c_ushort; 32],
517 DaylightDate: SYSTEMTIME,
518 DaylightBias: c_long,
519 }
520 extern "C" {
521 fn GetTimeZoneInformation(lpTimeZoneInformation: *mut TIME_ZONE_INFORMATION) -> c_int;
522 }
523 let mut tzi: TIME_ZONE_INFORMATION = Default::default();
524 GetTimeZoneInformation(&mut tzi);
525 let offset_hour: i16 = tzi.Bias as i16 / 60;
526 let offset_minute: i16 = tzi.Bias as i16 % 60;
527 TIME_OFFSET = Some(-(offset_hour * 100 + offset_minute));
528 }
529 return;
530}
531
532pub fn sleep(t: u64) -> Sleep {
534 use std::time::Duration;
535
536 return tokio::time::sleep(Duration::from_millis(t));
537}