summaryrefslogtreecommitdiffstats
path: root/melib/src/datetime.rs
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-01-06 16:10:36 +0200
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-01-06 16:10:36 +0200
commitc0ac643f0545a0364c3b18c0fa92705399f8b238 (patch)
treef89f7a73c1c578a84712e116fa38c6644b21ff76 /melib/src/datetime.rs
parentf6de511abdafb4cb08c0264df6e2c88cf88faaab (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.rs131
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);
+}