paiagram/units/
time.rs

1use bevy::prelude::Reflect;
2use serde::{Deserialize, Serialize};
3use std::ops;
4
5#[derive(
6    Reflect, Debug, Deserialize, Serialize, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord,
7)]
8pub struct TimetableTime(pub i32);
9
10impl TimetableTime {
11    #[inline]
12    pub fn as_duration(self) -> Duration {
13        Duration(self.0)
14    }
15    #[inline]
16    pub fn from_hms<T: Into<i32>>(h: T, m: T, s: T) -> Self {
17        TimetableTime(h.into() * 3600 + m.into() * 60 + s.into())
18    }
19    #[inline]
20    pub fn to_hmsd(self) -> (i32, i32, i32, i32) {
21        let days = self.0.div_euclid(24 * 3600);
22        let seconds_of_day = self.0.rem_euclid(24 * 3600);
23
24        let hours = seconds_of_day / 3600;
25        let minutes = (seconds_of_day % 3600) / 60;
26        let seconds = seconds_of_day % 60;
27
28        (hours, minutes, seconds, days)
29    }
30    #[inline]
31    pub fn from_str(s: &str) -> Option<Self> {
32        let parts: Vec<&str> = s.split(':').collect();
33        match parts.len() {
34            2 => {
35                let h = parts[0].parse::<i32>().ok()?;
36                let m = parts[1].parse::<i32>().ok()?;
37                Some(TimetableTime::from_hms(h, m, 0))
38            }
39            3 => {
40                let h = parts[0].parse::<i32>().ok()?;
41                let m = parts[1].parse::<i32>().ok()?;
42                let sec = parts[2].parse::<i32>().ok()?;
43                Some(TimetableTime::from_hms(h, m, sec))
44            }
45            _ => None,
46        }
47    }
48    #[inline]
49    pub fn from_oud2_str(s: &str) -> Option<Self> {
50        match s.len() {
51            3 => {
52                let h = s[0..1].parse::<i32>().ok()?;
53                let m = s[1..3].parse::<i32>().ok()?;
54                Some(TimetableTime::from_hms(h, m, 0))
55            }
56            4 => {
57                let h = s[0..2].parse::<i32>().ok()?;
58                let m = s[2..4].parse::<i32>().ok()?;
59                Some(TimetableTime::from_hms(h, m, 0))
60            }
61            5 => {
62                let h = s[0..1].parse::<i32>().ok()?;
63                let m = s[1..3].parse::<i32>().ok()?;
64                let sec = s[3..5].parse::<i32>().ok()?;
65                Some(TimetableTime::from_hms(h, m, sec))
66            }
67            6 => {
68                let h = s[0..2].parse::<i32>().ok()?;
69                let m = s[2..4].parse::<i32>().ok()?;
70                let sec = s[4..6].parse::<i32>().ok()?;
71                Some(TimetableTime::from_hms(h, m, sec))
72            }
73            _ => None,
74        }
75    }
76}
77
78impl std::fmt::Display for TimetableTime {
79    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        let days = self.0.div_euclid(24 * 3600);
81        let seconds_of_day = self.0.rem_euclid(24 * 3600);
82
83        let hours = seconds_of_day / 3600;
84        let minutes = (seconds_of_day % 3600) / 60;
85        let seconds = seconds_of_day % 60;
86
87        write!(f, "{:02}:{:02}:{:02}", hours, minutes, seconds)?;
88
89        if days != 0 {
90            let sign = if days > 0 { '+' } else { '-' };
91            write!(f, "{}{}", sign, days.abs())?;
92        }
93
94        Ok(())
95    }
96}
97
98impl ops::Sub<TimetableTime> for TimetableTime {
99    type Output = Duration;
100    fn sub(self, rhs: TimetableTime) -> Self::Output {
101        Duration(self.0 - rhs.0)
102    }
103}
104
105impl ops::Add<Duration> for TimetableTime {
106    type Output = TimetableTime;
107    fn add(self, rhs: Duration) -> Self::Output {
108        TimetableTime(self.0 + rhs.0)
109    }
110}
111
112impl ops::AddAssign<Duration> for TimetableTime {
113    fn add_assign(&mut self, rhs: Duration) {
114        self.0 += rhs.0
115    }
116}
117
118impl ops::Sub<Duration> for TimetableTime {
119    type Output = TimetableTime;
120    fn sub(self, rhs: Duration) -> Self::Output {
121        TimetableTime(self.0 - rhs.0)
122    }
123}
124
125impl ops::SubAssign<Duration> for TimetableTime {
126    fn sub_assign(&mut self, rhs: Duration) {
127        self.0 -= rhs.0;
128    }
129}
130
131#[derive(Reflect, Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
132pub struct Duration(pub i32);
133
134impl Duration {
135    #[inline]
136    pub fn to_hms(self) -> (i32, i32, i32) {
137        let hours = self.0 / 3600;
138        let minutes = (self.0 % 3600) / 60;
139        let seconds = self.0 % 60;
140        (hours, minutes, seconds)
141    }
142}
143
144impl Duration {
145    #[inline]
146    pub fn from_str(s: &str) -> Option<Self> {
147        let parts: Vec<&str> = s.split(':').collect();
148        match parts.len() {
149            2 => {
150                let h = parts[0].parse::<i32>().ok()?;
151                let m = parts[1].parse::<i32>().ok()?;
152                Some(Duration(h * 3600 + m * 60))
153            }
154            3 => {
155                let h = parts[0].parse::<i32>().ok()?;
156                let m = parts[1].parse::<i32>().ok()?;
157                let sec = parts[2].parse::<i32>().ok()?;
158                Some(Duration(h * 3600 + m * 60 + sec))
159            }
160            _ => None,
161        }
162    }
163}
164
165impl std::fmt::Display for Duration {
166    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167        let (h, m, s) = self.to_hms();
168        write!(f, ">> {:02}:{:02}:{:02}", h, m, s)
169    }
170}
171
172impl ops::Add<Duration> for Duration {
173    type Output = Duration;
174    fn add(self, rhs: Duration) -> Self::Output {
175        Duration(self.0 + rhs.0)
176    }
177}
178
179impl ops::AddAssign<Duration> for Duration {
180    fn add_assign(&mut self, rhs: Duration) {
181        self.0 += rhs.0;
182    }
183}
184
185impl ops::Sub<Duration> for Duration {
186    type Output = Duration;
187    fn sub(self, rhs: Duration) -> Self::Output {
188        Duration(self.0 - rhs.0)
189    }
190}
191
192impl ops::SubAssign<Duration> for Duration {
193    fn sub_assign(&mut self, rhs: Duration) {
194        self.0 -= rhs.0;
195    }
196}
197
198impl ops::Add<TimetableTime> for Duration {
199    type Output = TimetableTime;
200    fn add(self, rhs: TimetableTime) -> Self::Output {
201        TimetableTime(self.0 + rhs.0)
202    }
203}
204
205impl ops::Div<i32> for Duration {
206    type Output = Duration;
207    fn div(self, rhs: i32) -> Self::Output {
208        Duration(self.0 / rhs)
209    }
210}
211
212impl ops::DivAssign<i32> for Duration {
213    fn div_assign(&mut self, rhs: i32) {
214        self.0 /= rhs;
215    }
216}
217
218impl ops::Mul<i32> for Duration {
219    type Output = Duration;
220    fn mul(self, rhs: i32) -> Self::Output {
221        Duration(self.0 * rhs)
222    }
223}
224
225impl ops::MulAssign<i32> for Duration {
226    fn mul_assign(&mut self, rhs: i32) {
227        self.0 *= rhs;
228    }
229}
230
231impl ops::Mul<Duration> for i32 {
232    type Output = Duration;
233    fn mul(self, rhs: Duration) -> Self::Output {
234        Duration(self * rhs.0)
235    }
236}