1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2
3#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[repr(transparent)]
7pub struct OrbitEpoch(u64);
8
9impl OrbitEpoch {
10 pub const ZERO: Self = Self(0);
11
12 pub fn now() -> Self {
13 Self::from_system_time(SystemTime::now())
14 }
15
16 pub fn from_system_time(time: SystemTime) -> Self {
17 let millis = time
18 .duration_since(UNIX_EPOCH)
19 .unwrap_or_default()
20 .as_millis()
21 .min(u128::from(u64::MAX)) as u64;
22 Self(millis)
23 }
24
25 pub const fn from_unix_ms(epoch_ms: u64) -> Self {
26 Self(epoch_ms)
27 }
28
29 pub const fn as_unix_ms(self) -> u64 {
30 self.0
31 }
32
33 pub fn age_at(self, now: Self) -> Duration {
34 Duration::from_millis(now.0.saturating_sub(self.0))
35 }
36
37 pub fn is_fresh_at(self, now: Self, max_age: Duration) -> bool {
38 self.age_at(now) <= max_age
39 }
40}
41
42impl From<u64> for OrbitEpoch {
43 fn from(value: u64) -> Self {
44 Self::from_unix_ms(value)
45 }
46}
47
48impl From<OrbitEpoch> for u64 {
49 fn from(value: OrbitEpoch) -> Self {
50 value.as_unix_ms()
51 }
52}
53
54impl std::fmt::Display for OrbitEpoch {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{}", self.0)
57 }
58}