Skip to main content

ax_libc/
mktime.rs

1use core::ffi::c_int;
2
3use crate::ctypes;
4
5const MONTH_DAYS: [[c_int; 12]; 2] = [
6    // Non-leap years:
7    [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
8    // Leap years:
9    [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
10];
11
12#[inline(always)]
13fn leap_year(year: c_int) -> bool {
14    year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
15}
16
17/// Convert broken-down time into time since the Epoch.
18#[unsafe(no_mangle)]
19pub unsafe extern "C" fn mktime(t: *mut ctypes::tm) -> ctypes::time_t {
20    unsafe {
21        let mut year = (*t).tm_year + 1900;
22        let mut month = (*t).tm_mon;
23        let mut day = (*t).tm_mday as i64 - 1;
24
25        let leap = if leap_year(year) { 1 } else { 0 };
26
27        if year < 1970 {
28            day =
29                MONTH_DAYS[if leap_year(year) { 1 } else { 0 }][(*t).tm_mon as usize] as i64 - day;
30
31            while year < 1969 {
32                year += 1;
33                day += if leap_year(year) { 366 } else { 365 };
34            }
35
36            while month < 11 {
37                month += 1;
38                day += MONTH_DAYS[leap][month as usize] as i64;
39            }
40
41            (-(day * (60 * 60 * 24)
42                - (((*t).tm_hour as i64) * (60 * 60)
43                    + ((*t).tm_min as i64) * 60
44                    + (*t).tm_sec as i64))) as ctypes::time_t
45        } else {
46            while year > 1970 {
47                year -= 1;
48                day += if leap_year(year) { 366 } else { 365 };
49            }
50
51            while month > 0 {
52                month -= 1;
53                day += MONTH_DAYS[leap][month as usize] as i64;
54            }
55
56            (day * (60 * 60 * 24)
57                + ((*t).tm_hour as i64) * (60 * 60)
58                + ((*t).tm_min as i64) * 60
59                + (*t).tm_sec as i64) as ctypes::time_t
60        }
61    }
62}