diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-01-06 16:10:36 +0200 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2020-01-06 16:10:36 +0200 |
commit | c0ac643f0545a0364c3b18c0fa92705399f8b238 (patch) | |
tree | f89f7a73c1c578a84712e116fa38c6644b21ff76 /melib/src/datetime.rs | |
parent | f6de511abdafb4cb08c0264df6e2c88cf88faaab (diff) |
melib: add datetime module
Datetime module adds POSIX time functions interface
Diffstat (limited to 'melib/src/datetime.rs')
-rw-r--r-- | melib/src/datetime.rs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/melib/src/datetime.rs b/melib/src/datetime.rs new file mode 100644 index 00000000..7c56686f --- /dev/null +++ b/melib/src/datetime.rs @@ -0,0 +1,131 @@ +/* + * 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: Vec<u8> = vec![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); +} |