1use crate::errors::{TimeOverflow, TimeParserError};
5use crate::times::Time;
6use crate::TimeUnits;
7use chrono::{self, DateTime, Utc};
8use std::fmt::{self, Display, Formatter};
9use std::ops::{Add, Sub};
10use std::str::FromStr;
11
12#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Default, Clone, Copy)]
13pub struct TimeStamp {
14 time: DateTime<Utc>,
15}
16
17#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
18pub struct Duration {
19 duration: chrono::Duration,
20}
21
22impl Display for TimeStamp {
23 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
24 write!(f, "{}", self.time.to_rfc3339())
25 }
26}
27
28impl FromStr for TimeStamp {
29 type Err = TimeParserError;
30
31 fn from_str(string: &str) -> Result<Self, Self::Err> {
32 Ok(TimeStamp {
33 time: DateTime::parse_from_rfc3339(string)
34 .map_err(|_| TimeParserError)?
35 .into(),
36 })
37 }
38}
39
40impl<T: Into<Duration>> Add<T> for TimeStamp {
41 type Output = TimeStamp;
42
43 fn add(self, duration: T) -> Self::Output {
44 TimeStamp {
45 time: self.time + duration.into().duration,
46 }
47 }
48}
49
50impl<T: Into<Duration>> Sub<T> for TimeStamp {
51 type Output = TimeStamp;
52
53 fn sub(self, duration: T) -> Self::Output {
54 TimeStamp {
55 time: self.time - duration.into().duration,
56 }
57 }
58}
59
60impl Sub<Self> for TimeStamp {
61 type Output = Duration;
62
63 fn sub(self, other: Self) -> Self::Output {
64 Duration {
65 duration: self.time - other.time,
66 }
67 }
68}
69
70impl Time for TimeStamp {
71 type Duration = Duration;
72
73 fn now() -> Self {
74 TimeStamp { time: Utc::now() }
75 }
76
77 fn add(self, duration: Duration) -> Result<TimeStamp, TimeOverflow> {
78 Ok(TimeStamp {
79 time: self
80 .time
81 .checked_add_signed(duration.duration)
82 .ok_or(TimeOverflow)?,
83 })
84 }
85}
86
87impl TimeUnits for Duration {
88 fn seconds(seconds: i64) -> Self {
89 Duration {
90 duration: chrono::Duration::seconds(seconds),
91 }
92 }
93
94 fn num_seconds(&self) -> i64 {
95 self.duration.num_seconds()
96 }
97}
98
99impl From<i64> for Duration {
100 fn from(num: i64) -> Duration {
101 Duration::seconds(num)
102 }
103}