[niepce] rust: use chrono::DateTime



commit 1baaaad9e06b5e02892ef31219f952923881d1ae
Author: Hubert Figuière <hub figuiere net>
Date:   Mon Oct 9 20:34:56 2017 -0400

    rust: use chrono::DateTime

 Cargo.toml                    |    7 +-
 cbindgen.toml                 |   11 +++
 src/engine/db/libmetadata.rs  |   16 ++---
 src/engine/db/library.rs      |    6 +-
 src/fwk/base/date.rs          |  153 ++++++-----------------------------------
 src/fwk/base/propertyvalue.rs |    6 +-
 src/fwk/utils/exempi.rs       |   13 +++-
 src/lib.rs                    |    3 +-
 8 files changed, 60 insertions(+), 155 deletions(-)
---
diff --git a/Cargo.toml b/Cargo.toml
index 0e22de6..cedb2b0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,17 +5,18 @@ authors = ["Hubert Figuière <hub figuiere net>"]
 build = "build.rs"
 
 [dependencies]
-libc = "0.2.23"
-rusqlite = { version = "0.12.0", features = ["functions"] }
+chrono = "0.4.0"
 exempi = { version = "2.4.4", git = "https://github.com/hfiguiere/exempi-rs.git"; }
 glib-sys = "0.4.0"
 gio-sys = "0.4.0"
 gio = "0.2.0"
+libc = "0.2.23"
+rusqlite = { version = "0.12.0", features = ["functions"] }
 #gphoto = "0.1.1"
 
 [build-dependencies]
 bindgen = "0.30.0"
-cbindgen = { version = "0.1.23", git = "https://github.com/eqrion/cbindgen.git"; }
+cbindgen = { version = "0.1.25", git = "https://github.com/eqrion/cbindgen.git"; }
 pkg-config = "0.3.9"
 
 [lib]
diff --git a/cbindgen.toml b/cbindgen.toml
new file mode 100644
index 0000000..d2c45dc
--- /dev/null
+++ b/cbindgen.toml
@@ -0,0 +1,11 @@
+# An optional name to use as an include guard
+include_guard = "niepce_rust_bindings_h"
+
+# An optional namespace to output around the generated bindings
+namespace = "ffi"
+
+language = "C++"
+
+[parse]
+parse_deps = true
+include = ["chrono"]
diff --git a/src/engine/db/libmetadata.rs b/src/engine/db/libmetadata.rs
index 604880c..a65a462 100644
--- a/src/engine/db/libmetadata.rs
+++ b/src/engine/db/libmetadata.rs
@@ -20,15 +20,15 @@
 use std::ffi::CStr;
 use std::mem::transmute;
 use rusqlite;
+use chrono::Utc;
 use exempi;
 
-use fwk;
 use fwk::{
     PropertyValue,
     PropertyBag,
     PropertySet,
     XmpMeta,
-    make_xmp_date_time
+    xmp_date_from
 };
 use fwk::utils::exempi::{NS_XAP, NS_DC};
 use super::{
@@ -138,8 +138,9 @@ impl LibMetadata {
                     return true;
                 },
                 &PropertyValue::Date(ref d) => {
+                    let xmp_date = xmp_date_from(d);
                     return self.xmp.xmp.set_property_date(
-                        &ix.ns, &ix.property, d.xmp_date(), exempi::PROP_NONE);
+                        &ix.ns, &ix.property, &xmp_date, exempi::PROP_NONE);
                 }
             }
             err_out!("error setting property {}:{} {}", ix.ns, ix.property,
@@ -198,12 +199,9 @@ impl LibMetadata {
     }
 
     pub fn touch(&mut self) -> bool {
-        let mut xmpdate = exempi::DateTime::new();
-        if make_xmp_date_time(fwk::Date::now(), &mut xmpdate) {
-            return self.xmp.xmp.set_property_date(NS_XAP, "MetadataDate",
-                                                  &xmpdate, exempi::PROP_NONE);
-        }
-        false
+        let xmpdate = xmp_date_from(&Utc::now());
+        return self.xmp.xmp.set_property_date(NS_XAP, "MetadataDate",
+                                              &xmpdate, exempi::PROP_NONE);
     }
 }
 
diff --git a/src/engine/db/library.rs b/src/engine/db/library.rs
index 3ed3dbd..96d321f 100644
--- a/src/engine/db/library.rs
+++ b/src/engine/db/library.rs
@@ -23,6 +23,8 @@ use std::path::{
 };
 use std::fs::File;
 use std::io::Write;
+
+use chrono::Utc;
 use rusqlite;
 
 use super::{
@@ -418,7 +420,7 @@ impl Library {
             //label = meta.label().unwrap_or(String::from(""));
             flag = meta.flag().unwrap_or(0);
             if let Some(ref date) = meta.creation_date() {
-                creation_date = date.time_value();
+                creation_date = date.timestamp();
             } else {
                 creation_date = 0
             }
@@ -441,7 +443,7 @@ impl Library {
 
         if let Some(ref conn) = self.dbconn {
             let ifile_type = file_type as i32;
-            let time = fwk::Date::now();
+            let time = Utc::now().timestamp();
             ret = match conn.execute("INSERT INTO files (\
                                 main_file, name, parent_id, \
                                 import_date, mod_date, \
diff --git a/src/fwk/base/date.rs b/src/fwk/base/date.rs
index 5fe9928..2d51817 100644
--- a/src/fwk/base/date.rs
+++ b/src/fwk/base/date.rs
@@ -17,125 +17,30 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-use exempi;
 use libc;
 use std::ffi::CString;
-use std::ptr;
-use std::time::{
-    SystemTime,
-    UNIX_EPOCH
-};
-
-// i64 since rusql doesn't like u64.
-// Like a UNIX time_t (also i64)
-pub type Time = i64;
-
-#[derive(Clone,Debug)]
-pub enum Timezone {}
-
-///
-/// Class to deal with ISO8601 string dates as used by XMP.
-/// Bonus: with a timezone.
-/// XXX replace by chrono::DateTime<>
-///
-#[derive(Clone,Debug)]
-pub struct Date {
-    datetime: exempi::DateTime,
-    tz: Option<Timezone>,
-}
-
-
-impl Date {
-
-    pub fn new(dt: exempi::DateTime, tz: Option<Timezone>) -> Date {
-        Date { datetime: dt, tz: tz }
-    }
-
-    pub fn new_from_time(t: Time, tz: Option<Timezone>) -> Date {
-        let mut dt = exempi::DateTime::new();
-        make_xmp_date_time(t, &mut dt);
-        Date { datetime: dt, tz: tz }
-    }
-
-    pub fn tz(&self) -> &Option<Timezone> {
-        &self.tz
-    }
-    pub fn xmp_date(&self) -> &exempi::DateTime {
-        &self.datetime
-    }
-
-    pub fn time_value(&self) -> Time {
-        let value = self.xmp_date();
-        let mut dt = libc::tm {
-            tm_sec: value.c.second,
-            tm_min: value.c.minute,
-            tm_hour: value.c.hour,
-            tm_mday: value.c.day,
-            tm_mon: value.c.month,
-            tm_year: value.c.year - 1900,
-            tm_wday: 0, // ignored by mktime()
-            tm_yday: 0, // ignored by mktime()
-            tm_isdst: -1,
-            // this field is supposed to be a glibc extension. oh joy.
-            tm_gmtoff: value.c.tz_sign as i64 * ((value.c.tz_hour as i64 * 3600i64) +
-                                                 (value.c.tz_minute as i64 * 60i64)),
-            tm_zone: ptr::null_mut(),
-        };
-        let date = unsafe { libc::mktime(&mut dt) };
-        // XXX can't seem to use the macro here.
-        //dbg_assert!(date != -1, "date is -1");
-
-        date
-    }
-
-    pub fn now() -> Time {
-        let time: i64 = if let Ok(t) = SystemTime::now().duration_since(UNIX_EPOCH) {
-            t.as_secs()
-        } else {
-            0
-        } as i64;
-        time
-    }
 
-}
-
-impl ToString for Date {
-    fn to_string(&self) -> String {
-        format!("{0:04}:{1:02}:{2:02} {3:02}:{4:02}:{5:02} {6}{7:02}{8:02}",
-                self.datetime.c.year, self.datetime.c.month,
-                self.datetime.c.day, self.datetime.c.hour,
-                self.datetime.c.minute, self.datetime.c.second,
-                match self.datetime.c.tz_sign {
-                    exempi::XmpTzSign::West => '-',
-                    _ => '+'
-                },
-                self.datetime.c.tz_hour, self.datetime.c.tz_minute)
-    }
-}
-
-/**
- * Fill the XmpDateTime %xmp_dt from a %t
- * @return false if gmtime_r failed.
- */
-pub fn make_xmp_date_time(t: Time, xmp_dt: &mut exempi::DateTime) -> bool {
-    let pgmt = unsafe { libc::gmtime(&t) };
-    if pgmt.is_null() {
-        return false;
-    }
-    unsafe {
-        xmp_dt.c.year = (*pgmt).tm_year + 1900;
-        xmp_dt.c.month = (*pgmt).tm_mon + 1;
-        xmp_dt.c.day = (*pgmt).tm_mday;
-        xmp_dt.c.hour = (*pgmt).tm_hour;
-        xmp_dt.c.minute = (*pgmt).tm_min;
-        xmp_dt.c.second = (*pgmt).tm_sec;
-    }
-    xmp_dt.c.tz_sign = exempi::XmpTzSign::UTC;
-    xmp_dt.c.tz_hour = 0;
-    xmp_dt.c.tz_minute = 0;
-    xmp_dt.c.nano_second = 0;
+use chrono;
+use chrono::{Datelike, Timelike};
+use exempi;
 
-    return true;
+pub type Time = i64;
+pub type Date = chrono::DateTime<chrono::Utc>;
+
+pub fn xmp_date_from(d: &chrono::DateTime<chrono::Utc>) -> exempi::DateTime {
+    let mut xmp_date = exempi::DateTime::new();
+    xmp_date.c.year = d.year();
+    xmp_date.c.month = d.month() as i32;
+    xmp_date.c.day = d.day() as i32;
+    xmp_date.c.hour = d.hour() as i32;
+    xmp_date.c.minute = d.minute() as i32;
+    xmp_date.c.second = d.second() as i32;
+    xmp_date.c.tz_sign = exempi::XmpTzSign::UTC;
+    xmp_date.c.tz_hour = 0;
+    xmp_date.c.tz_minute = 0;
+    xmp_date.c.nano_second = 0;
+
+    xmp_date
 }
 
 #[no_mangle]
@@ -147,21 +52,3 @@ pub extern "C" fn fwk_date_delete(date: *mut Date) {
 pub extern "C" fn fwk_date_to_string(date: &Date) -> *mut libc::c_char {
     CString::new(date.to_string().as_bytes()).unwrap().into_raw()
 }
-
-#[cfg(test)]
-mod test {
-    use super::Date;
-
-    #[test]
-    fn test_date() {
-        let d = Date::new_from_time(0, None);
-        let xmp_dt = d.xmp_date();
-
-        assert_eq!(xmp_dt.c.year, 1970);
-        assert_eq!(xmp_dt.c.month, 1);
-        assert_eq!(xmp_dt.c.day, 1);
-
-        assert_eq!(d.to_string(), "1970:01:01 00:00:00 +0000");
-    }
-
-}
diff --git a/src/fwk/base/propertyvalue.rs b/src/fwk/base/propertyvalue.rs
index e91dd7b..977c8b0 100644
--- a/src/fwk/base/propertyvalue.rs
+++ b/src/fwk/base/propertyvalue.rs
@@ -19,8 +19,8 @@
 
 use libc::c_char;
 use std::ffi::{CStr,CString};
-use fwk::base::date::Date;
 
+use chrono::{DateTime, Utc};
 
 #[derive(Clone,Debug)]
 #[repr(C)]
@@ -29,12 +29,12 @@ pub enum PropertyValue {
     Int(i32),
     String(String),
     StringArray(Vec<String>),
-    Date(Date)
+    Date(DateTime<Utc>)
 }
 
+type Date = DateTime<Utc>;
 
 impl PropertyValue {
-
 }
 
 #[no_mangle]
diff --git a/src/fwk/utils/exempi.rs b/src/fwk/utils/exempi.rs
index 4d36990..04be75a 100644
--- a/src/fwk/utils/exempi.rs
+++ b/src/fwk/utils/exempi.rs
@@ -23,10 +23,12 @@ use std::fs::File;
 use std::io::prelude::*;
 use std::path::Path;
 use std::ptr;
+
+use chrono::{DateTime, Utc};
 use exempi;
 use exempi::Xmp;
-use fwk::Date;
 
+type Date = DateTime<Utc>;
 
 static NIEPCE_XMP_NAMESPACE: &'static str = "http://xmlns.figuiere.net/ns/niepce/1.0";;
 static NIEPCE_XMP_NS_PREFIX: &'static str = "niepce";
@@ -164,10 +166,13 @@ impl XmpMeta {
         return self.xmp.get_property_i32(NIEPCE_XMP_NAMESPACE, "Flag", &mut flags);
     }
 
-    pub fn creation_date(&self) -> Option<Date> {
+    pub fn creation_date(&self) -> Option<DateTime<Utc>> {
         let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
-        if let Some(date) = self.xmp.get_property_date(NS_EXIF, "DateTimeOriginal", &mut flags) {
-            return Some(Date::new(date, None));
+        if let Some(xmpstring) = self.xmp.get_property(NS_EXIF, "DateTimeOriginal", &mut flags) {
+            if let Ok(date) = DateTime::parse_from_rfc3339(xmpstring.to_str()) {
+                let utc_date = date.with_timezone(&Utc);
+                return Some(utc_date);
+            }
         }
         None
     }
diff --git a/src/lib.rs b/src/lib.rs
index 5917a20..9be6692 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,11 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+extern crate chrono;
 extern crate exempi;
-extern crate libc;
 extern crate glib_sys;
 extern crate gio_sys;
 extern crate gio;
+extern crate libc;
 extern crate rusqlite;
 
 #[macro_use]


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]