time_c/sys.rs
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//!Raw system types and functions
#![allow(non_camel_case_types)]
use crate::Time;
use core::{mem, ptr};
use core::ffi::{c_void, c_int, c_long};
///Alias to time_t.
///
///This crate supports 64bit time only
///
///## Note
///
///Your system uses 32bit for time()? Don't use this crate then
pub type time_t = i64;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
///C definition of decoded time.
pub struct tm {
///Seconds after the minute. Range 0-60
pub tm_sec: c_int,
///Minutes after the hour. Range 0-59
pub tm_min: c_int,
///Hours since midnight. Range 0-23
pub tm_hour: c_int,
///Day of the month. Range 1-31
pub tm_mday: c_int,
///Months since January. Range 0-11
pub tm_mon: c_int,
///Years since 1900
pub tm_year: c_int,
///days since Sunday. Range 0-6
pub tm_wday: c_int,
///days since January 1. Range 0-365
pub tm_yday: c_int,
/// Daylight Saving Time flag. Non-zero value indicates DST is present.
pub tm_isdst: c_int,
//Other fields are non-standard and depend on platform
//So don't care about these fields
_reserved: mem::MaybeUninit<[u8; mem::size_of::<c_long>() + mem::size_of::<*const c_void>() + mem::size_of::<c_int>()]>,
}
impl tm {
///Normalizes time to a more convenient struct for interpreting time components.
pub const fn normalize(&self) -> Time {
let tm {
tm_sec,
tm_min,
tm_hour,
tm_mday,
tm_mon,
tm_year,
tm_wday,
tm_yday,
tm_isdst,
..
} = self;
Time {
sec: *tm_sec as _,
min: *tm_min as _,
hour: *tm_hour as _,
month_day: *tm_mday as _,
month: (*tm_mon as u8).saturating_add(1),
year: (*tm_year as u16).saturating_add(1900),
week_day: *tm_wday as _,
day: *tm_yday as _,
is_dst: *tm_isdst > 0,
}
}
}
extern "C" {
#[cfg_attr(windows, link_name = "_time64")]
///Raw C API function to access time
pub fn time(time: *mut time_t) -> time_t;
}
///Gets current UTC time, if available.
pub fn get_time() -> Option<time_t> {
let result = unsafe {
time(ptr::null_mut())
};
match result {
-1 => None,
time => Some(time)
}
}
#[cfg(windows)]
///Parses UTC time into tm struct, if possible
pub fn utc_time(timer: &time_t) -> Option<tm> {
extern "C" {
#[link_name = "_gmtime64_s"]
pub fn gmtime_s(buf: *mut tm, timer: *const time_t) -> c_int;
}
let mut tm = mem::MaybeUninit::uninit();
let res = unsafe {
gmtime_s(tm.as_mut_ptr(), timer)
};
match res {
0 => unsafe {
Some(tm.assume_init())
},
_ => None,
}
}
#[cfg(not(windows))]
///Parses UTC time into tm struct, if possible
pub fn utc_time(timer: &time_t) -> Option<tm> {
extern "C" {
pub fn gmtime_r(timer: *const time_t, buf: *mut tm) -> *mut tm;
}
let mut tm = mem::MaybeUninit::uninit();
let res = unsafe {
gmtime_r(timer, tm.as_mut_ptr())
};
if res.is_null() {
None
} else {
unsafe {
Some(tm.assume_init())
}
}
}