1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use libc::{time_t, tm};
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Copy, Clone)]
pub struct Local {
    year: i32,
    month: u32,
    day: u32,
    hour: u32,
    minute: u32,
    second: u32,
    usec: u32,
}

impl Local {
    #[inline]
    pub fn now() -> Self {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("system time before Unix epoch");

        let res = local_time(now.as_secs() as time_t);
        Local {
            year: res.tm_year + 1900,
            month: (res.tm_mon + 1) as u32,
            day: res.tm_mday as u32,
            hour: res.tm_hour as u32,
            minute: res.tm_min as u32,
            second: res.tm_sec as u32,
            usec: now.subsec_micros(),
        }
    }

    #[inline]
    pub fn year(&self) -> i32 {
        self.year
    }

    #[inline]
    pub fn month(&self) -> u32 {
        self.month
    }

    #[inline]
    pub fn day(&self) -> u32 {
        self.day
    }

    #[inline]
    pub fn hour(&self) -> u32 {
        self.hour
    }

    #[inline]
    pub fn minute(&self) -> u32 {
        self.minute
    }

    #[inline]
    pub fn second(&self) -> u32 {
        self.second
    }

    #[inline]
    pub fn usec(&self) -> u32 {
        self.usec
    }
}

#[cfg(unix)]
fn local_time(time: time_t) -> tm {
    use libc::{c_char, localtime_r};

    let mut res = tm {
        tm_sec: 0,
        tm_min: 0,
        tm_hour: 0,
        tm_mday: 0,
        tm_mon: 0,
        tm_year: 0,
        tm_wday: 0,
        tm_yday: 0,
        tm_isdst: 0,
        tm_gmtoff: 0,
        tm_zone: std::ptr::null::<c_char>(),
    };
    unsafe {
        localtime_r(&time, &mut res);
    }
    res
}

#[cfg(windows)]
fn local_time(time: time_t) -> tm {
    use libc::localtime_s;

    let mut res = tm {
        tm_sec: 0,
        tm_min: 0,
        tm_hour: 0,
        tm_mday: 0,
        tm_mon: 0,
        tm_year: 0,
        tm_wday: 0,
        tm_yday: 0,
        tm_isdst: 0,
    };
    unsafe {
        localtime_s(&mut res, &time);
    }
    res
}