willow_data_model/timestamp/
mod.rs1use core::fmt;
2
3use core::ops::{Add, AddAssign, Sub, SubAssign};
4
5#[cfg(feature = "dev")]
6use arbitrary::Arbitrary;
7
8#[cfg(feature = "std")]
9use hifitime::HifitimeError;
10use hifitime::{Duration, Epoch, J2000_REF_EPOCH};
11
12use order_theory::{
13 GreatestElement, LeastElement, LowerSemilattice, PredecessorExceptForLeast,
14 SuccessorExceptForGreatest, TryPredecessor, TrySuccessor, UpperSemilattice,
15};
16
17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
33#[cfg_attr(feature = "dev", derive(Arbitrary))]
34pub struct Timestamp(u64);
35
36impl fmt::Display for Timestamp {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 Epoch::from(*self).fmt(f)
39 }
40}
41
42impl From<u64> for Timestamp {
43 fn from(value: u64) -> Self {
44 Self(value)
45 }
46}
47
48impl From<Timestamp> for u64 {
49 fn from(value: Timestamp) -> Self {
50 value.0
51 }
52}
53
54impl AsRef<u64> for Timestamp {
55 fn as_ref(&self) -> &u64 {
56 &self.0
57 }
58}
59
60impl AsMut<u64> for Timestamp {
61 fn as_mut(&mut self) -> &mut u64 {
62 &mut self.0
63 }
64}
65
66impl TryFrom<Epoch> for Timestamp {
68 type Error = <i128 as TryInto<u64>>::Error;
69
70 fn try_from(value: Epoch) -> Result<Self, Self::Error> {
72 let diff = value - J2000_REF_EPOCH;
73 let microseconds = diff.total_nanoseconds() / 1000;
74 Ok(Self(microseconds.try_into()?))
75 }
76}
77
78impl From<Timestamp> for Epoch {
79 fn from(value: Timestamp) -> Self {
80 let duration_from_j2000 = Duration::from(value);
81 J2000_REF_EPOCH + duration_from_j2000
82 }
83}
84
85impl TryFrom<Duration> for Timestamp {
87 type Error = <i128 as TryInto<u64>>::Error;
88
89 fn try_from(value: Duration) -> Result<Self, Self::Error> {
91 Ok(Self((value.total_nanoseconds() / 1000).try_into()?))
92 }
93}
94
95impl From<Timestamp> for Duration {
97 fn from(value: Timestamp) -> Self {
98 Duration::from_total_nanoseconds((value.0 as i128) * 1000)
99 }
100}
101
102impl Timestamp {
103 #[cfg(feature = "std")]
105 pub fn now() -> Result<Self, HifitimeError> {
106 Self::try_from(Epoch::now()?).map_err(|_| HifitimeError::SystemTimeError)
107 }
108}
109
110impl Add<Duration> for Timestamp {
111 type Output = Self;
112
113 fn add(self, rhs: Duration) -> Self::Output {
114 (Duration::from(self) + rhs)
115 .try_into()
116 .expect("Timestamp overflow!")
117 }
118}
119
120impl AddAssign<Duration> for Timestamp {
121 fn add_assign(&mut self, rhs: Duration) {
122 *self = *self + rhs;
123 }
124}
125
126impl Add for Timestamp {
127 type Output = Self;
128
129 fn add(self, rhs: Self) -> Self::Output {
130 Self(self.0 + rhs.0)
131 }
132}
133
134impl AddAssign for Timestamp {
135 fn add_assign(&mut self, rhs: Self) {
136 *self = Self(self.0 + rhs.0);
137 }
138}
139
140impl Sub<Duration> for Timestamp {
141 type Output = Self;
142
143 fn sub(self, rhs: Duration) -> Self::Output {
144 (Duration::from(self) - rhs)
145 .try_into()
146 .expect("Timestamp overflow!")
147 }
148}
149
150impl SubAssign<Duration> for Timestamp {
151 fn sub_assign(&mut self, rhs: Duration) {
152 *self = *self - rhs;
153 }
154}
155
156impl Sub for Timestamp {
157 type Output = Self;
158
159 fn sub(self, rhs: Self) -> Self::Output {
160 Self(self.0 - rhs.0)
161 }
162}
163
164impl SubAssign for Timestamp {
165 fn sub_assign(&mut self, rhs: Self) {
166 *self = Self(self.0 - rhs.0);
167 }
168}
169
170impl LeastElement for Timestamp {
171 fn least() -> Self {
172 u64::least().into()
173 }
174}
175
176impl GreatestElement for Timestamp {
177 fn greatest() -> Self {
178 u64::greatest().into()
179 }
180}
181
182impl LowerSemilattice for Timestamp {
183 fn greatest_lower_bound(&self, other: &Self) -> Self {
184 self.0.greatest_lower_bound(other.as_ref()).into()
185 }
186}
187
188impl UpperSemilattice for Timestamp {
189 fn least_upper_bound(&self, other: &Self) -> Self {
190 self.0.least_upper_bound(other.as_ref()).into()
191 }
192}
193
194impl TryPredecessor for Timestamp {
195 fn try_predecessor(&self) -> Option<Self> {
196 self.0.try_predecessor().map(Self)
197 }
198}
199
200impl TrySuccessor for Timestamp {
201 fn try_successor(&self) -> Option<Self> {
202 self.0.try_successor().map(Self)
203 }
204}
205
206impl PredecessorExceptForLeast for Timestamp {}
207
208impl SuccessorExceptForGreatest for Timestamp {}