subtile/time/
time_point.rs1use core::fmt;
2use std::ops::Neg;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct TimePoint(i64);
7
8impl TimePoint {
9 #[must_use]
11 pub const fn from_msecs(time: i64) -> Self {
12 Self(time)
13 }
14
15 #[must_use]
22 pub fn from_secs(seconds: f64) -> Self {
23 let msecs = cast::i64(seconds * 1000.0).unwrap();
24 Self(msecs)
25 }
26
27 #[must_use]
29 pub fn to_secs(self) -> f64 {
30 self.0 as f64 / 1000.
31 }
32
33 #[must_use]
35 pub const fn msecs(self) -> i64 {
36 self.0
37 }
38
39 const fn secs(self) -> i64 {
40 self.0 / 1000
41 }
42
43 const fn mins(self) -> i64 {
44 self.0 / (60 * 1000)
45 }
46
47 const fn hours(self) -> i64 {
48 self.0 / (60 * 60 * 1000)
49 }
50 const fn mins_comp(self) -> i64 {
51 self.mins() % 60
52 }
53
54 const fn secs_comp(self) -> i64 {
55 self.secs() % 60
56 }
57
58 const fn msecs_comp(self) -> i64 {
59 self.msecs() % 1000
60 }
61}
62
63impl Neg for TimePoint {
64 type Output = Self;
65 fn neg(self) -> Self {
66 Self(-self.0)
67 }
68}
69
70impl TimePoint {
71 pub fn fmt_separator(&self, f: &mut fmt::Formatter<'_>, separator: char) -> fmt::Result {
76 let t = if self.0 < 0 { -*self } else { *self };
77 write!(
78 f,
79 "{}{:02}:{:02}:{:02}{separator}{:03}",
80 if self.0 < 0 { "-" } else { "" },
81 t.hours(),
82 t.mins_comp(),
83 t.secs_comp(),
84 t.msecs_comp()
85 )
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn time_point_creation() {
95 assert_eq!(TimePoint::from_msecs(6751), TimePoint(6751));
96 assert_eq!(TimePoint::from_msecs(142), TimePoint::from_secs(0.142));
97 }
98
99 #[test]
100 fn time_point_creation_with_too_much_decimals() {
101 assert_eq!(TimePoint::from_msecs(265), TimePoint::from_secs(0.265_579));
102 assert_eq!(TimePoint(142), TimePoint::from_secs(0.142_75));
103 }
104
105 #[test]
106 fn time_point_msecs() {
107 const TIME: i64 = 62487;
108 assert_eq!(TimePoint::from_msecs(TIME).msecs(), TIME);
109 }
110
111 #[test]
112 fn time_point_secs() {
113 const TIME: f64 = 624.87;
114 assert_eq!(TimePoint::from_secs(TIME).secs(), 624);
115 }
116
117 #[test]
118 fn to_big_seconds() {
119 const TIME: f64 = 9_223_372_036_854_776.; let result = std::panic::catch_unwind(|| TimePoint::from_secs(TIME));
121 assert!(result.is_err());
122 }
123}