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}