1use std::time::{Duration, SystemTime, UNIX_EPOCH};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9pub struct Time {
10 pub sec: u64,
12 pub nsec: u32,
14}
15
16impl Time {
17 pub fn new(sec: u64, nsec: u32) -> Self {
19 let mut time = Self { sec, nsec };
20 time.normalize();
21 time
22 }
23
24 pub fn now() -> Self {
26 let now = SystemTime::now()
27 .duration_since(UNIX_EPOCH)
28 .expect("System time before Unix epoch");
29 Self::from(now)
30 }
31
32 pub fn from_duration(duration: Duration) -> Self {
34 Self::new(duration.as_secs(), duration.subsec_nanos())
35 }
36
37 pub fn to_duration(&self) -> Duration {
39 Duration::new(self.sec, self.nsec)
40 }
41
42 fn normalize(&mut self) {
44 if self.nsec >= 1_000_000_000 {
45 self.sec += u64::from(self.nsec) / 1_000_000_000;
46 self.nsec %= 1_000_000_000;
47 }
48 }
49
50 pub fn add(&self, duration: Duration) -> Self {
52 let duration_since_epoch = self.to_duration();
53 let new_duration = duration_since_epoch + duration;
54 Self::from_duration(new_duration)
55 }
56
57 pub fn sub(&self, duration: Duration) -> Self {
59 let duration_since_epoch = self.to_duration();
60 let new_duration = duration_since_epoch
61 .checked_sub(duration)
62 .unwrap_or_else(|| Duration::new(0, 0));
63 Self::from_duration(new_duration)
64 }
65}
66
67impl From<Duration> for Time {
68 fn from(duration: Duration) -> Self {
69 Self::from_duration(duration)
70 }
71}
72
73impl From<SystemTime> for Time {
74 fn from(time: SystemTime) -> Self {
75 let duration = time
76 .duration_since(UNIX_EPOCH)
77 .expect("System time before Unix epoch");
78 Self::from(duration)
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
86pub struct ZenobufDuration {
87 pub sec: i32,
89 pub nsec: i32,
91}
92
93impl ZenobufDuration {
94 pub fn new(sec: i32, nsec: i32) -> Self {
96 let mut duration = Self { sec, nsec };
97 duration.normalize();
98 duration
99 }
100
101 pub fn from_std(duration: Duration) -> Self {
103 Self::new(duration.as_secs() as i32, duration.subsec_nanos() as i32)
104 }
105
106 pub fn to_std(&self) -> Duration {
108 Duration::new(self.sec as u64, self.nsec as u32)
109 }
110
111 fn normalize(&mut self) {
113 if self.nsec >= 1_000_000_000 {
114 self.sec += self.nsec / 1_000_000_000;
115 self.nsec %= 1_000_000_000;
116 } else if self.nsec < 0 {
117 let sec_adj = (-self.nsec / 1_000_000_000) + 1;
118 self.sec -= sec_adj;
119 self.nsec += sec_adj * 1_000_000_000;
120 }
121 }
122}
123
124impl From<Duration> for ZenobufDuration {
125 fn from(duration: Duration) -> Self {
126 Self::from_std(duration)
127 }
128}
129
130impl From<ZenobufDuration> for Duration {
131 fn from(duration: ZenobufDuration) -> Self {
132 duration.to_std()
133 }
134}