chronologic/wins/
timestamp.rs

1use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
2use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
3use std::time::SystemTime;
4
5use crate::*;
6
7/// # A UTC timestamp (date + time)
8#[derive(Copy, Clone, Default, Hash, Eq, PartialEq, Ord, PartialOrd)]
9#[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Timestamp(pub(crate) TimeValue);
11
12/// A trait for marking timestamped data
13pub trait Timestamped {
14    /// Gets the timestamp
15    fn timestamp(&self) -> Timestamp;
16}
17
18
19impl Timestamp {
20
21    /// Creates a timepoint relative to the origin
22    #[inline]
23    pub fn from_origin(t: TimeValue) -> Self { Self(t) }
24
25    #[inline]
26    pub fn now() -> Self {
27        Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().into())
28    }
29
30    #[inline]
31    pub fn elapsed(&self) -> TimeValue { Self::now() - *self }
32
33    #[inline]
34    pub fn to_datetime(&self) -> DateTime<Utc> { Utc.from_utc_datetime(&(*self).into()) }
35
36    #[inline]
37    pub fn floor(self, period:TimeValue) -> Self
38    {
39        Self(self.0.floor(period))
40    }
41
42    #[inline]
43    pub fn ceil(self, period:TimeValue) -> Self
44    {
45        Self(self.0.ceil(period))
46    }
47
48    /// Duration since origin
49    #[inline]
50    pub fn since_origin(self) -> TimeValue { self.0 }
51}
52
53
54impl Neg for Timestamp {
55    type Output = Self;
56    #[inline] fn neg(self) -> Self::Output { Self(-self.0) }
57}
58
59impl TimePoint for Timestamp
60{
61    const INFINITE: Self = Self(TimeValue::INFINITE);
62    #[inline] fn is_finite(&self) -> bool { self.0.is_finite() }
63    #[inline] fn is_future_infinite(&self) -> bool { self.0.is_future_infinite() }
64    #[inline] fn is_past_infinite(&self) -> bool { self.0.is_past_infinite() }
65    #[inline] fn just_after(&self) -> Self { Self(self.0.just_after()) }
66    #[inline] fn just_before(&self) -> Self { Self(self.0.just_before()) }
67}
68
69impl TimeBounds for Timestamp
70{
71    type TimePoint = Self;
72    #[inline] fn is_empty(&self) -> bool { false }
73    #[inline] fn is_singleton(&self) -> bool { true }
74    #[inline] fn is_bounded(&self) -> bool { self.is_finite() }
75    #[inline] fn is_low_bounded(&self) -> bool { self.is_finite() }
76    #[inline] fn is_up_bounded(&self) -> bool { self.is_finite() }
77    #[inline] fn lower_bound(&self) -> Self::TimePoint { *self }
78    #[inline] fn upper_bound(&self) -> Self::TimePoint { *self }
79}
80
81impl TimeConvex for Timestamp { }
82
83
84impl Timestamped for Timestamp
85{
86    #[inline] fn timestamp(&self) -> Timestamp { *self }
87}
88
89impl<T:Timestamped> Timestamped for &T
90{
91    #[inline] fn timestamp(&self) -> Timestamp { T::timestamp(self) }
92}
93
94impl From<Timestamp> for NaiveDateTime
95{
96    #[inline]
97    fn from(value: Timestamp) -> Self {
98        NaiveDateTime::from_timestamp_opt( value.0.as_secs(), value.0.subsec_nanos() as u32).unwrap()
99    }
100}
101
102impl From<NaiveDateTime> for Timestamp
103{
104    #[inline]
105    fn from(t: NaiveDateTime) -> Self {
106        Self(TimeValue::from_nanos(t.timestamp_nanos_opt().unwrap()))
107    }
108}
109
110
111impl<Tz:TimeZone> From<DateTime<Tz>> for Timestamp
112{
113    #[inline]
114    fn from(t: DateTime<Tz>) -> Self {
115        Self(TimeValue::from_nanos(t.timestamp_nanos_opt().unwrap()))
116    }
117}
118
119
120
121impl Sub for Timestamp {
122    type Output = TimeValue;
123    /// Distance between two timestamps
124    #[inline] fn sub(self, other: Self) -> Self::Output { self.0 - other.0 }
125}
126
127impl Add<TimeValue> for Timestamp
128{
129    type Output = Self;
130    #[inline] fn add(self, other: TimeValue) -> Self::Output { Self(self.0+other) }
131}
132
133impl Sub<TimeValue> for Timestamp
134{
135    type Output = Self;
136    #[inline] fn sub(self, other: TimeValue) -> Self::Output { Self(self.0-other) }
137}
138
139impl AddAssign<TimeValue> for Timestamp
140{
141    #[inline]
142    fn add_assign(&mut self, other: TimeValue) { self.0 += other; }
143}
144
145impl SubAssign<TimeValue> for Timestamp
146{
147    #[inline]
148    fn sub_assign(&mut self, other: TimeValue) { self.0 -= other; }
149}
150
151impl Add<Timestamp> for TimeValue {
152    type Output = Timestamp;
153    #[inline] fn add(self, tw: Self::Output) -> Self::Output { tw + self }
154}
155
156impl Sub<Timestamp> for TimeValue {
157    type Output = Timestamp;
158    #[inline] fn sub(self, tw: Self::Output) -> Self::Output { (-tw) + self }
159}