summaryrefslogtreecommitdiffstats
path: root/src/icalwrap
diff options
context:
space:
mode:
authorVincent Breitmoser <look@my.amazin.horse>2019-01-25 20:06:09 +0100
committerVincent Breitmoser <look@my.amazin.horse>2019-01-25 20:06:09 +0100
commit8c476036178ed5011606053a550bead317e0a4b2 (patch)
tree1b1d62fa3e842e299f11404ed18ca47654886ab9 /src/icalwrap
parent530c85b176bfa1eb2f920c79eb49ff92c48a749d (diff)
icalwrap: add IcalDuration type
Diffstat (limited to 'src/icalwrap')
-rw-r--r--src/icalwrap/icalduration.rs177
-rw-r--r--src/icalwrap/icaltime.rs24
-rw-r--r--src/icalwrap/icalvevent.rs21
-rw-r--r--src/icalwrap/mod.rs16
4 files changed, 229 insertions, 9 deletions
diff --git a/src/icalwrap/icalduration.rs b/src/icalwrap/icalduration.rs
new file mode 100644
index 0000000..96fd073
--- /dev/null
+++ b/src/icalwrap/icalduration.rs
@@ -0,0 +1,177 @@
+use std::ops::{Deref,Add};
+use std::ffi::{CStr,CString};
+use ical;
+use std::fmt::{Error,Display,Formatter};
+use std::str::FromStr;
+use std::cmp::Ordering;
+
+
+#[derive(Clone,Debug)]
+pub struct IcalDuration {
+ duration: ical::icaldurationtype,
+}
+
+impl IcalDuration {
+ pub fn from_seconds(seconds: i32) -> IcalDuration {
+ let duration = unsafe { ical::icaldurationtype_from_int(seconds) };
+ IcalDuration{ duration }
+ }
+
+ pub fn to_seconds(&self) -> i32 {
+ unsafe { ical::icaldurationtype_as_int(self.duration) }
+ }
+}
+
+impl Deref for IcalDuration {
+ type Target = ical::icaldurationtype;
+
+ fn deref(&self) -> &ical::icaldurationtype {
+ &self.duration
+ }
+}
+
+impl Display for IcalDuration {
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+ let cstr = unsafe {
+ CStr::from_ptr(ical::icaldurationtype_as_ical_string(self.duration))
+ };
+ let string = cstr.to_string_lossy();
+ write!(f, "{}", string)
+ }
+}
+
+impl FromStr for IcalDuration {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let c_str = CString::new(s).unwrap();
+ let duration = unsafe {
+ let duration = ical::icaldurationtype_from_string(c_str.as_ptr());
+ if ical::icaldurationtype_is_null_duration(duration) == 0 {
+ Some(duration)
+ } else {
+ None
+ }
+ };
+ if let Some(duration) = duration {
+ Ok(IcalDuration { duration })
+ } else {
+ return Err(format!("Could not parse duration {}", s));
+ }
+ }
+}
+
+impl PartialEq<IcalDuration> for IcalDuration {
+ fn eq(&self, rhs: &IcalDuration) -> bool {
+ self.to_seconds() == rhs.to_seconds()
+ }
+}
+
+impl Eq for IcalDuration {}
+
+impl PartialOrd for IcalDuration {
+ fn partial_cmp(&self, rhs: &IcalDuration) -> Option<Ordering> {
+ Some(self.cmp(rhs))
+ }
+}
+
+impl Ord for IcalDuration {
+ fn cmp(&self, rhs: &IcalDuration) -> Ordering {
+ let left = self.to_seconds();
+ let right = rhs.to_seconds();
+ if left == right {
+ Ordering::Equal
+ } else if left < right {
+ Ordering::Less
+ } else {
+ Ordering::Greater
+ }
+ }
+}
+
+impl From<ical::icaldurationtype> for IcalDuration {
+ fn from(duration: ical::icaldurationtype) -> IcalDuration {
+ IcalDuration { duration }
+ }
+}
+
+impl From<IcalDuration> for chrono::Duration {
+ fn from(duration: IcalDuration) -> chrono::Duration {
+ chrono::Duration::seconds(i64::from(duration.to_seconds()))
+ }
+}
+
+impl From<chrono::Duration> for IcalDuration {
+ fn from(duration: chrono::Duration) -> IcalDuration {
+ IcalDuration::from_seconds(duration.num_seconds() as i32)
+ }
+}
+impl Add for IcalDuration {
+ type Output = IcalDuration;
+
+ fn add(self, other: IcalDuration) -> IcalDuration {
+ let seconds = self.to_seconds() + other.to_seconds();
+ IcalDuration::from_seconds(seconds)
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_parse() {
+ let duration = "PT86400S".parse::<IcalDuration>().unwrap();
+ assert_eq!(IcalDuration::from_seconds(24*60*60), duration);
+ assert_eq!(86400, duration.to_seconds());
+ }
+
+ #[test]
+ fn test_parse_fail() {
+ let duration = "swag".parse::<IcalDuration>();
+ assert!(duration.is_err());
+ }
+
+ #[test]
+ fn test_display() {
+ let duration = IcalDuration::from_seconds(5*24*60*60 + 22*60*60 + 33*60 + 33);
+ assert_eq!("P5DT22H33M33S", duration.to_string());
+ }
+
+ #[test]
+ fn test_to_chrono() {
+ let from_duration = IcalDuration::from_seconds(5*24*60*60 + 22*60*60 + 33*60 + 33);
+ let duration: chrono::Duration = from_duration.into();
+ assert_eq!(chrono::Duration::seconds(5*24*60*60 + 22*60*60 + 33*60 + 33), duration);
+ }
+
+ #[test]
+ fn test_from_chrono() {
+ let from_duration = chrono::Duration::seconds(5*24*60*60 + 22*60*60 + 33*60 + 33);
+ let duration: IcalDuration = from_duration.into();
+ assert_eq!(IcalDuration::from_seconds(5*24*60*60 + 22*60*60 + 33*60 + 33), duration);
+ }
+
+ #[test]
+ fn test_add() {
+ let fst = IcalDuration::from_seconds(123);
+ let snd = IcalDuration::from_seconds(4567);
+
+ let sum = fst + snd;
+
+ assert_eq!(IcalDuration::from_seconds(123+4567), sum);
+ }
+
+ #[test]
+ fn test_cmp() {
+ let more = chrono::Duration::seconds(49128);
+ let less = chrono::Duration::seconds(5);
+
+ assert!(less == less);
+ assert!(more == more);
+ assert!(less < more);
+ assert!(!(more < less));
+ assert!(!(more == less));
+ }
+}
diff --git a/src/icalwrap/icaltime.rs b/src/icalwrap/icaltime.rs
index c618885..96a6368 100644
--- a/src/icalwrap/icaltime.rs
+++ b/src/icalwrap/icaltime.rs
@@ -1,9 +1,10 @@
-use std::ops::Deref;
+use std::ops::{Add,Deref};
use std::ffi::{CStr,CString};
use chrono::{Date,DateTime,TimeZone,Utc,Local};
use ical;
use utils::dateutil;
use super::IcalTimeZone;
+use super::IcalDuration;
use super::TZ_MUTEX;
use std::fmt::{Error,Display,Formatter};
use std::str::FromStr;
@@ -116,7 +117,7 @@ impl Display for IcalTime {
let cstr = unsafe {
CStr::from_ptr(ical::icaltime_as_ical_string(self.time))
};
- let string = cstr.to_string_lossy().into_owned();
+ let string = cstr.to_string_lossy();
write!(f, "{}", string)
}
}
@@ -158,6 +159,15 @@ impl From<ical::icaltimetype> for IcalTime {
}
}
+impl Add<IcalDuration> for IcalTime {
+ type Output = IcalTime;
+
+ fn add(self, other: IcalDuration) -> IcalTime {
+ let time = unsafe { ical::icaltime_add(self.time, *other) };
+ IcalTime { time }
+ }
+}
+
impl<T: Into<IcalTime> + Clone> From<&T> for IcalTime {
fn from(time: &T) -> IcalTime {
time.clone().into()
@@ -273,4 +283,14 @@ mod tests {
assert_eq!("20140101", time.to_string());
}
+
+ #[test]
+ fn test_add() {
+ let now = IcalTime::utc();
+ let duration = IcalDuration::from_seconds(123);
+
+ let sum = now + duration;
+
+ assert_eq!(1357002123 + 123, sum.timestamp());
+ }
}
diff --git a/src/icalwrap/icalvevent.rs b/src/icalwrap/icalvevent.rs
index f4adf0f..15bd9c0 100644
--- a/src/icalwrap/icalvevent.rs
+++ b/src/icalwrap/icalvevent.rs
@@ -4,6 +4,7 @@ use super::IcalComponent;
use super::IcalVCalendar;
use super::IcalTime;
use super::IcalTimeZone;
+use super::IcalDuration;
use ical;
pub struct IcalVEvent {
@@ -62,6 +63,17 @@ impl IcalVEvent {
}
}
+ pub fn get_duration(&self) -> Option<IcalDuration> {
+ unsafe {
+ let duration = ical::icalcomponent_get_duration(self.ptr);
+ if ical::icaldurationtype_is_bad_duration(duration) == 0 {
+ Some(IcalDuration::from(duration))
+ } else {
+ None
+ }
+ }
+ }
+
pub fn get_dtstart(&self) -> Option<IcalTime> {
match self.instance_timestamp {
Some(ref timestamp) => Some(timestamp.clone()),
@@ -269,6 +281,15 @@ mod tests {
}
#[test]
+ fn test_get_duration() {
+ let cal = IcalVCalendar::from_str(testdata::TEST_EVENT_MULTIDAY, None).unwrap();
+ let event = cal.get_principal_event();
+
+ assert_eq!(Some(IcalDuration::from_seconds(10*24*60*60 + 18*60*60)), event.get_duration());
+ }
+
+
+ #[test]
fn test_get_description() {
let cal = IcalVCalendar::from_str(testdata::TEST_EVENT_ONE_MEETING, None).unwrap();
let event = cal.get_principal_event();
diff --git a/src/icalwrap/mod.rs b/src/icalwrap/mod.rs
index b8b6fb9..e52aabe 100644
--- a/src/icalwrap/mod.rs
+++ b/src/icalwrap/mod.rs
@@ -1,9 +1,10 @@
-mod icalvcalendar;
-mod icalvevent;
-mod icalproperty;
mod icalcomponent;
+mod icalduration;
+mod icalproperty;
mod icaltime;
mod icaltimezone;
+mod icalvcalendar;
+mod icalvevent;
// libical does some weird, non-threadsafe things in timezone methods, notably
// icaltime_convert_to_zone (which is also called in icaltime_as_timet_with_zone)
@@ -15,10 +16,11 @@ lazy_static! {
static ref TZ_MUTEX: Mutex<i32> = Mutex::new(0);
}
-pub use self::icalvcalendar::IcalVCalendar;
-pub use self::icalvcalendar::IcalEventIter;
-pub use self::icalvevent::IcalVEvent;
-pub use self::icalproperty::IcalProperty;
pub use self::icalcomponent::IcalComponent;
+pub use self::icalduration::IcalDuration;
+pub use self::icalproperty::IcalProperty;
pub use self::icaltime::IcalTime;
pub use self::icaltimezone::IcalTimeZone;
+pub use self::icalvcalendar::IcalEventIter;
+pub use self::icalvcalendar::IcalVCalendar;
+pub use self::icalvevent::IcalVEvent;