ros_message/
time.rs
1use serde_derive::{Deserialize, Serialize};
2use std::cmp;
3use std::convert::TryInto;
4use std::fmt::Formatter;
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::ops;
8use std::time;
9
10const BILLION: i64 = 1_000_000_000;
11
12#[derive(Copy, Clone, Default, Serialize, Deserialize, Debug, Eq)]
14pub struct Time {
15 pub sec: u32,
17 pub nsec: u32,
19}
20
21impl Hash for Time {
22 fn hash<H: Hasher>(&self, state: &mut H) {
23 self.nanos().hash(state)
24 }
25}
26
27impl Time {
28 #[inline]
37 pub fn new() -> Time {
38 Self::default()
39 }
40
41 #[inline]
51 pub fn from_nanos(t: i64) -> Time {
52 Time {
53 sec: (t / BILLION) as u32,
54 nsec: (t % BILLION) as u32,
55 }
56 }
57
58 #[inline]
68 pub fn from_seconds(sec: u32) -> Time {
69 Time { sec, nsec: 0 }
70 }
71
72 #[inline]
82 pub fn nanos(self) -> i64 {
83 i64::from(self.sec) * BILLION + i64::from(self.nsec)
84 }
85
86 #[inline]
96 pub fn seconds(self) -> f64 {
97 f64::from(self.sec) + f64::from(self.nsec) / BILLION as f64
98 }
99}
100
101fn display_nanos(nanos: &str, f: &mut Formatter<'_>) -> fmt::Result {
102 let split_point = nanos.len() - 9;
105 let characters = nanos.chars();
106 let (left, right) = characters.as_str().split_at(split_point);
107 write!(f, "{}.{}", left, right)
108}
109
110impl fmt::Display for Time {
111 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
112 display_nanos(&format!("{:010}", self.nanos()), f)
113 }
114}
115
116impl cmp::PartialEq for Time {
117 fn eq(&self, other: &Self) -> bool {
118 self.nanos() == other.nanos()
119 }
120}
121
122impl cmp::PartialOrd for Time {
123 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
124 self.nanos().partial_cmp(&other.nanos())
125 }
126}
127
128impl cmp::Ord for Time {
129 fn cmp(&self, other: &Self) -> cmp::Ordering {
130 self.nanos().cmp(&other.nanos())
131 }
132}
133
134impl From<time::SystemTime> for Time {
135 fn from(other: time::SystemTime) -> Self {
136 let epoch = time::SystemTime::UNIX_EPOCH;
137 let elapsed = other.duration_since(epoch)
138 .expect("Dates before 1970 are not supported by the ROS time format");
139 let sec = elapsed.as_secs()
140 .try_into()
141 .expect("Dates after 2100 are not supported by the ROS time format");
142 Self {
143 sec,
144 nsec: elapsed.subsec_nanos(),
145 }
146 }
147}
148
149impl From<Time> for time::SystemTime {
150 fn from(other: Time) -> Self {
151 let elapsed = time::Duration::new(other.sec.into(), other.nsec);
152 time::SystemTime::UNIX_EPOCH + elapsed
153 }
154}
155
156#[derive(Copy, Clone, Default, Serialize, Deserialize, Debug, Eq)]
158pub struct Duration {
159 pub sec: i32,
161 pub nsec: i32,
163}
164
165impl Hash for Duration {
166 fn hash<H: Hasher>(&self, state: &mut H) {
167 self.nanos().hash(state)
168 }
169}
170
171impl fmt::Display for Duration {
172 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173 let data = self.nanos();
174 display_nanos(
175 &format!(
176 "{}{:010}",
177 if data.is_negative() { "-" } else { "" },
178 data.abs()
179 ),
180 f,
181 )
182 }
183}
184
185impl Duration {
186 #[inline]
195 pub fn new() -> Duration {
196 Self::default()
197 }
198
199 #[inline]
210 pub fn from_nanos(t: i64) -> Duration {
211 Duration {
212 sec: (t / BILLION) as i32,
213 nsec: (t % BILLION) as i32,
214 }
215 }
216
217 #[inline]
228 pub fn from_seconds(sec: i32) -> Duration {
229 Duration { sec, nsec: 0 }
230 }
231
232 #[inline]
243 pub fn nanos(self) -> i64 {
244 i64::from(self.sec) * BILLION + i64::from(self.nsec)
245 }
246
247 #[inline]
258 pub fn seconds(self) -> f64 {
259 f64::from(self.sec) + f64::from(self.nsec) / BILLION as f64
260 }
261}
262
263impl cmp::PartialEq for Duration {
264 fn eq(&self, other: &Self) -> bool {
265 self.nanos() == other.nanos()
266 }
267}
268
269impl cmp::PartialOrd for Duration {
270 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
271 self.nanos().partial_cmp(&other.nanos())
272 }
273}
274
275impl cmp::Ord for Duration {
276 fn cmp(&self, other: &Self) -> cmp::Ordering {
277 self.nanos().cmp(&other.nanos())
278 }
279}
280
281impl ops::Add<Duration> for Time {
282 type Output = Time;
283 fn add(self, rhs: Duration) -> Self::Output {
284 Time::from_nanos(self.nanos() + rhs.nanos())
285 }
286}
287
288impl ops::Add<Duration> for Duration {
289 type Output = Duration;
290 fn add(self, rhs: Duration) -> Self::Output {
291 Duration::from_nanos(self.nanos() + rhs.nanos())
292 }
293}
294
295impl ops::Sub<Time> for Time {
296 type Output = Duration;
297 fn sub(self, rhs: Time) -> Self::Output {
298 Duration::from_nanos(self.nanos() - rhs.nanos())
299 }
300}
301
302impl ops::Sub<Duration> for Time {
303 type Output = Time;
304 fn sub(self, rhs: Duration) -> Self::Output {
305 Time::from_nanos(self.nanos() - rhs.nanos())
306 }
307}
308
309impl ops::Sub<Duration> for Duration {
310 type Output = Duration;
311 fn sub(self, rhs: Duration) -> Self::Output {
312 Duration::from_nanos(self.nanos() - rhs.nanos())
313 }
314}
315
316impl ops::Neg for Duration {
317 type Output = Duration;
318 fn neg(self) -> Self::Output {
319 Duration {
320 sec: -self.sec,
321 nsec: -self.nsec,
322 }
323 }
324}
325
326impl From<time::Duration> for Duration {
327 fn from(std_duration: time::Duration) -> Self {
328 let sec = std_duration.as_secs()
329 .try_into()
330 .expect("Durations longer than 68 years are not supported by the ROS time format");
331 Duration {
332 sec,
333 nsec: std_duration.subsec_nanos() as i32,
334 }
335 }
336}
337
338impl From<Duration> for time::Duration {
339 fn from(other: Duration) -> Self {
340 let mut extra_sec = other.nsec / 1_000_000_000;
341 let mut nsec = other.nsec % 1_000_000_000;
342 if nsec < 0 {
343 extra_sec -= 1;
344 nsec += 1_000_000_000;
345 }
346
347 Self::new(
348 (other.sec + extra_sec).try_into().unwrap(),
349 nsec as u32,
350 )
351 }
352}