1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2
3use crate::Error;
4
5#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
6pub struct Timestamp(pub(crate) Duration);
7
8const ANSI_EPOCH_DIFF_NANOS: u64 = 11_644_473_600_000_000_000;
9
10impl Timestamp {
11 pub fn now() -> Self {
15 Self(
16 SystemTime::now()
17 .duration_since(UNIX_EPOCH)
18 .expect("System time is below UNIX EPOCH"),
19 )
20 }
21 pub fn now_rounded() -> Self {
22 let t = Self::now();
23 Self(Duration::from_secs(t.0.as_secs()))
24 }
25 #[inline]
26 pub fn elapsed(self) -> Result<Duration, Error> {
27 let now = Timestamp::now();
28 if now >= self {
29 Ok(now.0 - self.0)
30 } else {
31 Err(Error::TimeWentBackward)
32 }
33 }
34 #[inline]
35 pub fn duration_since(self, earlier: Self) -> Result<Duration, Error> {
36 if self >= earlier {
37 Ok(self.0 - earlier.0)
38 } else {
39 Err(Error::TimeWentBackward)
40 }
41 }
42 pub fn try_from_ansi_to_unix(self) -> Result<Self, Error> {
57 Ok(Self(Duration::from_nanos(
58 u64::try_from(self.0.as_nanos())?
59 .checked_sub(ANSI_EPOCH_DIFF_NANOS)
60 .ok_or_else(|| Error::Convert("Failed to convert from ANSI to UNIX".to_string()))?,
61 )))
62 }
63 pub fn try_from_unix_to_ansi(self) -> Result<Self, Error> {
67 Ok(Self(Duration::from_nanos(
68 u64::try_from(self.0.as_nanos())?
69 .checked_add(ANSI_EPOCH_DIFF_NANOS)
70 .ok_or_else(|| Error::Convert("Failed to convert from UNIX to ANSI".to_string()))?,
71 )))
72 }
73}