paiagram/units/
time.rs

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