mirror of https://git.meli.delivery/meli/meli
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.7 KiB
Rust
132 lines
3.7 KiB
Rust
/*
|
|
* meli - melib POSIX libc time interface
|
|
*
|
|
* Copyright 2020 Manos Pitsidianakis
|
|
*
|
|
* This file is part of meli.
|
|
*
|
|
* meli is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* meli is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
use std::convert::TryInto;
|
|
use std::ffi::{CStr, CString};
|
|
|
|
pub type UnixTimestamp = u64;
|
|
|
|
use libc::{timeval, timezone};
|
|
|
|
extern "C" {
|
|
fn strptime(
|
|
s: *const ::std::os::raw::c_char,
|
|
format: *const ::std::os::raw::c_char,
|
|
tm: *mut ::libc::tm,
|
|
) -> *const ::std::os::raw::c_char;
|
|
|
|
fn strftime(
|
|
s: *mut ::std::os::raw::c_char,
|
|
max: ::libc::size_t,
|
|
format: *const ::std::os::raw::c_char,
|
|
tm: *const ::libc::tm,
|
|
) -> ::libc::size_t;
|
|
|
|
fn mktime(tm: *const ::libc::tm) -> ::libc::time_t;
|
|
|
|
fn localtime_r(timep: *const ::libc::time_t, tm: *mut ::libc::tm) -> *mut ::libc::tm;
|
|
|
|
fn gettimeofday(tv: *mut timeval, tz: *mut timezone) -> i32;
|
|
}
|
|
|
|
pub fn timestamp_to_string(timestamp: UnixTimestamp, fmt: Option<&str>) -> String {
|
|
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
|
unsafe {
|
|
let i: i64 = timestamp.try_into().unwrap_or(0);
|
|
localtime_r(&i as *const i64, &mut new_tm as *mut ::libc::tm);
|
|
}
|
|
let fmt = fmt.map(|slice| CString::new(slice).unwrap());
|
|
let format: &CStr = if let Some(ref s) = fmt {
|
|
&s
|
|
} else {
|
|
unsafe { CStr::from_bytes_with_nul_unchecked(b"%a, %d %b %Y %T %z\0") }
|
|
};
|
|
let s: CString;
|
|
unsafe {
|
|
let mut vec: [u8; 256] = [0; 256];
|
|
let ret = strftime(
|
|
vec.as_mut_ptr() as *mut _,
|
|
256,
|
|
format.as_ptr(),
|
|
&new_tm as *const _,
|
|
);
|
|
s = CString::new(&vec[0..ret]).unwrap();
|
|
}
|
|
|
|
s.to_string_lossy().to_string()
|
|
}
|
|
|
|
pub fn rfc822_to_timestamp<T>(s: T) -> UnixTimestamp
|
|
where
|
|
T: Into<Vec<u8>>,
|
|
{
|
|
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
|
unsafe {
|
|
let fmt = CStr::from_bytes_with_nul_unchecked(b"%a, %e %h %Y %H:%M:%S %z\0");
|
|
let ret = strptime(
|
|
CString::new(s).unwrap().as_ptr(),
|
|
fmt.as_ptr(),
|
|
&mut new_tm as *mut _,
|
|
);
|
|
if ret.is_null() {
|
|
return 0;
|
|
}
|
|
return mktime(&new_tm as *const _) as u64;
|
|
}
|
|
}
|
|
|
|
pub fn timestamp_from_string<T>(s: T, fmt: &str) -> Option<UnixTimestamp>
|
|
where
|
|
T: Into<Vec<u8>>,
|
|
{
|
|
let mut new_tm: ::libc::tm = unsafe { std::mem::zeroed() };
|
|
let fmt = CString::new(fmt).unwrap();
|
|
unsafe {
|
|
let ret = strptime(
|
|
CString::new(s).unwrap().as_ptr(),
|
|
fmt.as_ptr(),
|
|
&mut new_tm as *mut _,
|
|
);
|
|
if ret.is_null() {
|
|
return None;
|
|
}
|
|
return Some(mktime(&new_tm as *const _) as u64);
|
|
}
|
|
}
|
|
|
|
pub fn now() -> UnixTimestamp {
|
|
use std::mem::MaybeUninit;
|
|
let mut tv = MaybeUninit::<::libc::timeval>::uninit();
|
|
let mut tz = MaybeUninit::<::libc::timezone>::uninit();
|
|
unsafe {
|
|
let ret = gettimeofday(tv.as_mut_ptr(), tz.as_mut_ptr());
|
|
if ret == -1 {
|
|
unreachable!("gettimeofday returned -1");
|
|
}
|
|
(tv.assume_init()).tv_sec as UnixTimestamp
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_timestamp() {
|
|
timestamp_to_string(0);
|
|
}
|