use std::time::SystemTime; /// Filter based on time ranges. #[derive(Debug, PartialEq)] pub enum TimeFilter { Before(SystemTime), After(SystemTime), } impl TimeFilter { fn from_str(ref_time: &SystemTime, s: &str) -> Option { humantime::parse_duration(s) .map(|duration| *ref_time - duration) .or_else(|_| humantime::parse_rfc3339_weak(s)) .ok() } pub fn before(ref_time: &SystemTime, s: &str) -> Option { TimeFilter::from_str(ref_time, s).map(TimeFilter::Before) } pub fn after(ref_time: &SystemTime, s: &str) -> Option { TimeFilter::from_str(ref_time, s).map(TimeFilter::After) } pub fn applies_to(&self, t: &SystemTime) -> bool { match self { TimeFilter::Before(limit) => t <= limit, TimeFilter::After(limit) => t >= limit, } } } #[cfg(test)] mod tests { use super::*; use std::time::Duration; #[test] fn is_time_filter_applicable() { let ref_time = humantime::parse_rfc3339("2010-10-10T10:10:10Z").unwrap(); assert!(TimeFilter::after(&ref_time, "1min") .unwrap() .applies_to(&ref_time)); assert!(!TimeFilter::before(&ref_time, "1min") .unwrap() .applies_to(&ref_time)); let t1m_ago = ref_time - Duration::from_secs(60); assert!(!TimeFilter::after(&ref_time, "30sec") .unwrap() .applies_to(&t1m_ago)); assert!(TimeFilter::after(&ref_time, "2min") .unwrap() .applies_to(&t1m_ago)); assert!(TimeFilter::before(&ref_time, "30sec") .unwrap() .applies_to(&t1m_ago)); assert!(!TimeFilter::before(&ref_time, "2min") .unwrap() .applies_to(&t1m_ago)); let t10s_before = "2010-10-10 10:10:00"; assert!(!TimeFilter::before(&ref_time, t10s_before) .unwrap() .applies_to(&ref_time)); assert!(TimeFilter::before(&ref_time, t10s_before) .unwrap() .applies_to(&t1m_ago)); assert!(TimeFilter::after(&ref_time, t10s_before) .unwrap() .applies_to(&ref_time)); assert!(!TimeFilter::after(&ref_time, t10s_before) .unwrap() .applies_to(&t1m_ago)); } }