aw_models/
timeinterval.rs

1use std::fmt;
2
3use serde::de::{self, Deserialize, Deserializer, Visitor};
4
5use chrono::DateTime;
6use chrono::Duration;
7use chrono::Utc;
8
9// TODO: Implement serialize
10
11#[derive(Clone, Debug)]
12pub struct TimeInterval {
13    start: DateTime<Utc>,
14    end: DateTime<Utc>,
15}
16
17#[derive(Debug)]
18pub enum TimeIntervalError {
19    ParseError(),
20}
21
22impl TimeInterval {
23    pub fn new(start: DateTime<Utc>, end: DateTime<Utc>) -> TimeInterval {
24        TimeInterval { start, end }
25    }
26
27    pub fn new_from_string(period: &str) -> Result<TimeInterval, TimeIntervalError> {
28        let splits = period.split('/').collect::<Vec<&str>>();
29        if splits.len() != 2 {
30            return Err(TimeIntervalError::ParseError());
31        }
32        let start = match DateTime::parse_from_rfc3339(splits[0]) {
33            Ok(dt) => dt.with_timezone(&Utc),
34            Err(_e) => return Err(TimeIntervalError::ParseError()),
35        };
36        let end = match DateTime::parse_from_rfc3339(splits[1]) {
37            Ok(dt) => dt.with_timezone(&Utc),
38            Err(_e) => return Err(TimeIntervalError::ParseError()),
39        };
40
41        Ok(TimeInterval::new(start, end))
42    }
43
44    pub fn start(&self) -> &DateTime<Utc> {
45        &self.start
46    }
47
48    pub fn end(&self) -> &DateTime<Utc> {
49        &self.end
50    }
51
52    pub fn duration(&self) -> Duration {
53        self.end - self.start
54    }
55}
56
57impl fmt::Display for TimeInterval {
58    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59        write!(f, "{}/{}", self.start.to_rfc3339(), self.end.to_rfc3339())
60    }
61}
62
63struct TimeIntervalVisitor;
64use serde::de::Unexpected;
65
66impl<'de> Visitor<'de> for TimeIntervalVisitor {
67    type Value = TimeInterval;
68
69    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70        formatter.write_str("an string in ISO timeinterval format (such as 2000-01-01T00:00:00+01:00/2001-02-02T01:01:01+01:00)")
71    }
72
73    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
74    where
75        E: de::Error,
76    {
77        match TimeInterval::new_from_string(&value) {
78            Ok(ti) => Ok(ti),
79            Err(e) => {
80                warn!("{:?}", e);
81                Err(de::Error::invalid_value(Unexpected::Str(value), &self))
82            }
83        }
84    }
85}
86
87impl<'de> Deserialize<'de> for TimeInterval {
88    fn deserialize<D>(deserializer: D) -> Result<TimeInterval, D::Error>
89    where
90        D: Deserializer<'de>,
91    {
92        deserializer.deserialize_str(TimeIntervalVisitor)
93    }
94}
95
96#[test]
97fn test_timeinterval() {
98    use std::str::FromStr;
99
100    let start = DateTime::from_str("2000-01-01T00:00:00Z").unwrap();
101    let end = DateTime::from_str("2000-01-02T00:00:00Z").unwrap();
102    let period_str = "2000-01-01T00:00:00+00:00/2000-01-02T00:00:00+00:00";
103    let duration = end - start;
104    let tp = TimeInterval::new(start, end);
105    assert_eq!(tp.start(), &start);
106    assert_eq!(tp.end(), &end);
107    assert_eq!(tp.duration(), duration);
108    assert_eq!(tp.to_string(), period_str);
109
110    let tp = TimeInterval::new_from_string(period_str).unwrap();
111    assert_eq!(tp.start(), &start);
112    assert_eq!(tp.end(), &end);
113    assert_eq!(tp.duration(), duration);
114    assert_eq!(tp.to_string(), period_str);
115}