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}