1use std::{
4 fmt,
5 ops::{Add, AddAssign, Deref, DerefMut, Sub, SubAssign},
6 time::{Duration, Instant, SystemTime},
7};
8
9use time::{
10 error::IndeterminateOffset, format_description::well_known::Rfc3339, OffsetDateTime, UtcOffset,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct SystemInstant {
19 system_time: SystemTime,
20 instant: Instant,
21}
22
23impl SystemInstant {
24 #[must_use]
25 pub const fn new(system_time: SystemTime, instant: Instant) -> Self {
26 Self {
27 system_time,
28 instant,
29 }
30 }
31
32 #[must_use]
33 pub fn now() -> Self {
34 let system_time = SystemTime::now();
35 let instant = Instant::now();
39 Self::new(system_time, instant)
40 }
41
42 #[must_use]
43 pub fn system_time(&self) -> SystemTime {
44 self.system_time
45 }
46
47 #[must_use]
48 pub fn instant(&self) -> Instant {
49 self.instant
50 }
51
52 #[must_use]
53 pub fn timestamp_utc(&self) -> Timestamp {
54 TimestampInner::from(self.system_time).into()
55 }
56
57 #[must_use]
58 pub fn checked_duration_since_instant(&self, since_instant: Instant) -> Option<Duration> {
59 self.instant.checked_duration_since(since_instant)
60 }
61
62 #[must_use]
63 pub fn checked_duration_until_instant(&self, until_instant: Instant) -> Option<Duration> {
64 until_instant.checked_duration_since(self.instant)
65 }
66
67 #[must_use]
68 pub fn checked_system_time_for_instant(&self, instant: Instant) -> Option<SystemTime> {
69 if self.instant < instant {
70 self.system_time
71 .checked_add(instant.duration_since(self.instant))
72 } else {
73 self.system_time
74 .checked_sub(self.instant.duration_since(instant))
75 }
76 }
77}
78
79impl Add<Duration> for SystemInstant {
80 type Output = Self;
81
82 fn add(self, rhs: Duration) -> Self {
83 let Self {
84 system_time,
85 instant,
86 } = self;
87 Self::new(system_time + rhs, instant + rhs)
88 }
89}
90
91impl AddAssign<Duration> for SystemInstant {
92 fn add_assign(&mut self, rhs: Duration) {
93 let Self {
94 mut system_time,
95 mut instant,
96 } = self;
97 system_time += rhs;
98 instant += rhs;
99 }
100}
101
102type TimestampInner = OffsetDateTime;
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
106pub struct Timestamp(TimestampInner);
107
108impl Timestamp {
109 #[must_use]
110 pub const fn new(inner: TimestampInner) -> Self {
111 Self(inner)
112 }
113
114 #[must_use]
115 pub const fn to_inner(self) -> TimestampInner {
116 let Self(inner) = self;
117 inner
118 }
119
120 #[must_use]
121 pub const fn to_utc(self) -> Self {
122 Self(self.to_inner().to_offset(UtcOffset::UTC))
123 }
124
125 #[must_use]
134 pub fn now() -> Self {
135 TimestampInner::now_local()
136 .unwrap_or_else(|_: IndeterminateOffset| TimestampInner::now_utc())
137 .into()
138 }
139
140 #[must_use]
142 pub fn now_utc() -> Self {
143 TimestampInner::now_utc().into()
144 }
145
146 pub fn parse_rfc3339(input: &str) -> Result<Self, time::error::Parse> {
147 TimestampInner::parse(input, &Rfc3339).map(Self::new)
148 }
149
150 pub fn format_rfc3339(&self) -> Result<String, time::error::Format> {
151 self.0.format(&Rfc3339)
152 }
153
154 pub fn format_rfc3339_into<W: std::io::Write>(
155 &self,
156 output: &mut W,
157 ) -> Result<usize, time::error::Format> {
158 self.0.format_into(output, &Rfc3339)
159 }
160}
161
162impl From<TimestampInner> for Timestamp {
163 fn from(inner: TimestampInner) -> Self {
164 Self::new(inner)
165 }
166}
167
168impl From<Timestamp> for TimestampInner {
169 fn from(from: Timestamp) -> Self {
170 from.to_inner()
171 }
172}
173
174impl From<SystemTime> for Timestamp {
175 fn from(system_time: SystemTime) -> Self {
176 Self::new(system_time.into())
177 }
178}
179
180impl From<Timestamp> for SystemTime {
181 fn from(from: Timestamp) -> Self {
182 from.to_inner().into()
183 }
184}
185
186impl AsRef<TimestampInner> for Timestamp {
187 fn as_ref(&self) -> &TimestampInner {
188 &self.0
189 }
190}
191
192impl Deref for Timestamp {
193 type Target = TimestampInner;
194
195 fn deref(&self) -> &TimestampInner {
196 self.as_ref()
197 }
198}
199
200impl DerefMut for Timestamp {
201 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
202 let Self(inner) = self;
203 inner
204 }
205}
206
207impl fmt::Display for Timestamp {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 self.as_ref().fmt(f)
210 }
211}
212
213#[cfg(feature = "serde")]
214impl serde::Serialize for Timestamp {
215 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: serde::Serializer,
218 {
219 time::serde::rfc3339::serialize(self.as_ref(), serializer)
220 }
221}
222
223#[cfg(feature = "serde")]
224impl<'de> serde::Deserialize<'de> for Timestamp {
225 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
226 where
227 D: serde::Deserializer<'de>,
228 {
229 time::serde::rfc3339::deserialize(deserializer).map(Self::new)
230 }
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234pub enum Interval {
235 Nanos(u32),
236 Micros(u32),
237 Millis(u32),
238 Seconds(u32),
239 Minutes(u32),
240 Hours(u32),
241 Days(u32),
242 Weeks(u32),
243}
244
245impl Interval {
246 fn as_duration(self) -> Duration {
247 match self {
248 Self::Nanos(nanos) => Duration::from_nanos(u64::from(nanos)),
249 Self::Micros(micros) => Duration::from_micros(u64::from(micros)),
250 Self::Millis(millis) => Duration::from_millis(u64::from(millis)),
251 Self::Seconds(secs) => Duration::from_secs(u64::from(secs)),
252 Self::Minutes(mins) => Duration::from_secs(u64::from(mins) * 60),
253 Self::Hours(hrs) => Duration::from_secs(u64::from(hrs) * 60 * 60),
254 Self::Days(days) => Duration::from_secs(u64::from(days) * 60 * 60 * 24),
255 Self::Weeks(weeks) => Duration::from_secs(u64::from(weeks) * 60 * 60 * 24 * 7),
256 }
257 }
258
259 #[must_use]
260 pub fn system_time_before(&self, system_time: SystemTime) -> SystemTime {
261 system_time - self.as_duration()
262 }
263
264 #[must_use]
265 pub fn system_time_after(&self, system_time: SystemTime) -> SystemTime {
266 system_time + self.as_duration()
267 }
268}
269
270impl Add<Interval> for Timestamp {
271 type Output = Timestamp;
272
273 fn add(self, interval: Interval) -> Self::Output {
274 (self.to_inner() + interval.as_duration()).into()
275 }
276}
277
278impl AddAssign<Interval> for Timestamp {
279 fn add_assign(&mut self, interval: Interval) {
280 *self = *self + interval;
281 }
282}
283
284impl Sub<Interval> for Timestamp {
285 type Output = Timestamp;
286
287 fn sub(self, interval: Interval) -> Self::Output {
288 (self.to_inner() - interval.as_duration()).into()
289 }
290}
291
292impl SubAssign<Interval> for Timestamp {
293 fn sub_assign(&mut self, interval: Interval) {
294 *self = *self - interval;
295 }
296}