1#![no_std]
2#![allow(clippy::needless_return)]
3
4use core::ffi::{c_int, c_long, c_char};
7#[cfg(unix)] use core::mem::MaybeUninit;
8
9#[allow(non_camel_case_types)]
11pub type time_t = i64;
12
13#[repr(C)]
15#[derive(Default, Debug, Clone, Copy)]
16pub struct Tm {
17 pub tm_sec: c_int,
19 pub tm_min: c_int,
21 pub tm_hour: c_int,
23 pub tm_mday: c_int,
25 pub tm_mon: c_int,
27 pub tm_year: c_int,
29 pub tm_wday: c_int,
31 pub tm_yday: c_int,
33 pub tm_isdst: c_int,
35 pub tm_gmtoff: c_long,
37 pub tm_zone: *const c_char,
39}
40
41mod sys {
42 use super::{Tm, time_t};
43 unsafe extern "C" {
44 pub fn time(tloc: *mut time_t) -> time_t;
45 #[cfg(windows)]
46 pub fn gmtime(timep: *const time_t) -> *mut Tm;
47 #[cfg(unix)]
48 pub fn gmtime_r(timep: *const time_t, result: *mut Tm) -> *mut Tm;
49 #[cfg(windows)]
50 pub fn localtime(timep: *const time_t) -> *mut Tm;
51 #[cfg(unix)]
52 pub fn localtime_r(timep: *const time_t, result: *mut Tm) -> *mut Tm;
53 #[cfg(windows)]
54 pub fn mkgmtime(timeptr: *mut Tm) -> time_t;
55 #[cfg(unix)]
56 pub fn timegm(tm: *mut Tm) -> time_t;
57 }
58}
59
60pub fn time() -> time_t {
62 unsafe { sys::time(core::ptr::null_mut()) }
63}
64
65pub fn gmtime(time: time_t) -> Option<Tm> {
69 #[cfg(windows)] unsafe {
70 let ret = sys::gmtime(&time as *const time_t);
71 if ret.is_null() { return None; }
72 return Some(*ret);
73 }
74
75 #[cfg(unix)] unsafe {
76 let mut tm = MaybeUninit::zeroed();
77 let ret = sys::gmtime_r(&time as *const time_t, tm.as_mut_ptr());
78 if ret.is_null() { return None; }
79 return Some(tm.assume_init());
80 };
81}
82
83pub fn localtime(time: time_t) -> Option<Tm> {
85 #[cfg(windows)] unsafe {
86 let ret = sys::localtime(&time as *const time_t);
87 if ret.is_null() { return None; }
88 return Some(*ret);
89 }
90
91 #[cfg(unix)] unsafe {
92 let mut tm = MaybeUninit::zeroed();
93 let ret = sys::localtime_r(&time as *const time_t, tm.as_mut_ptr());
94 if ret.is_null() { return None; }
95 return Some(tm.assume_init());
96 };
97}
98
99pub fn timegm(mut tm: Tm) -> Option<time_t> {
104 let ret;
105 #[cfg(windows)] unsafe {
106 ret = sys::mkgmtime(&mut tm as *mut Tm);
107 }
108
109 #[cfg(unix)] unsafe {
110 ret = sys::timegm(&mut tm as *mut Tm);
111 }
112
113 if ret == -1 { return None; }
114 Some(ret)
115}
116
117#[cfg(test)]
118mod test {
119 use super::*;
120
121 #[test]
122 fn test_gmtime() {
123 let tm = gmtime(1740607859).unwrap();
124 assert_eq!(3, tm.tm_wday); assert_eq!(26, tm.tm_mday);
127 assert_eq!(1, tm.tm_mon); assert_eq!(125, tm.tm_year); assert_eq!(22, tm.tm_hour);
130 assert_eq!(10, tm.tm_min);
131 assert_eq!(59, tm.tm_sec); }
133
134 #[test]
135 fn test_timegm() {
136 let tm = Tm {
137 tm_year: 2026 - 1900,
138 tm_mon: 0,
139 tm_mday: 3,
140 tm_hour: 23,
141 tm_min: 6,
142 tm_sec: 46,
143 ..Default::default()
144 };
145 assert_eq!(1767481606, timegm(tm).unwrap());
146 }
147}