hexga_math/other/
time.rs

1use super::*;
2
3/* 
4pub type DeltaTime = Rel<Time>;
5pub type FixedTime = Fix<Time>;
6*/
7
8pub type Time = TimeOf<float>;
9pub type DeltaTime = Time;
10pub type DeltaTimeOf<T> = TimeOf<T>;
11
12pub trait TimeExtension
13{
14    type Output;
15    fn ms  (self) -> Self::Output;
16    fn s   (self) -> Self::Output;
17    /// With an `s` to avoid the confusion with the min function
18    fn mins(self) -> Self::Output;
19    fn hour(self) -> Self::Output;
20    fn day (self) -> Self::Output;
21}
22impl_composite_output_with_methods!(TimeExtension, ms, s, mins, hour, day);
23
24impl<T> TimeExtension for T where T : ToFloat<Output = float>
25{
26    type Output = Time;
27
28    fn ms  (self) -> Self::Output { Time::from_ms(self.to_float()) }
29    fn s   (self) -> Self::Output { Time::from_s(self.to_float()) }
30    fn mins(self) -> Self::Output { Time::from_mins(self.to_float()) }
31    fn hour(self) -> Self::Output { Time::from_hour(self.to_float()) }
32    fn day (self) -> Self::Output { Time::from_day(self.to_float()) }
33}
34
35/// Represents time using, which can be used as an instant or a duration.
36/// 
37/// Provides conversion to other time units (seconds, minutes, days...).
38#[derive(Clone, Copy, PartialEq, PartialOrd, Default)]
39pub struct TimeOf<T:FloatingNumber> { second : T }
40
41impl<T:FloatingNumber> Debug for TimeOf<T> { fn fmt(&self, f: &mut Formatter<'_>) -> DResult { write!(f, "{}", self) } }
42
43impl<T:FloatingNumber> TimeOf<T>
44{
45    /// don't display the value if zero
46    fn display_non_zero_unit(f: &mut Formatter<'_>, val : i32, unit : &str) -> DResult 
47    { if val != 0 {  Self::display_unit(f, val, unit)?; write!(f, " ") } else { Ok(())} }
48
49    fn display_unit(f: &mut Formatter<'_>, val : i32, unit : &str) -> DResult 
50    { write!(f, "{}{}", val, unit) }
51}
52
53impl<T:FloatingNumber> Display for TimeOf<T>
54{
55    fn fmt(&self, f: &mut Formatter<'_>) -> DResult 
56    {
57        if self.is_zero() { return write!(f, "0s"); }
58
59        if self.is_strictly_negative() { write!(f, "-")?; }
60
61        Self::display_non_zero_unit(f, self.timer_day(), "d")?;
62        Self::display_non_zero_unit(f, self.timer_hour(), "h")?;
63        Self::display_non_zero_unit(f, self.timer_mins(), "m")?;
64        Self::display_non_zero_unit(f, self.timer_s(), "s")?;
65        Self::display_non_zero_unit(f, self.timer_ms(), "ms")?;
66        Ok(())
67    }
68}
69
70
71impl<T:FloatingNumber> Zero for TimeOf<T> { const ZERO : Self = Self::from_s(T::ZERO); }
72
73impl<T:FloatingNumber> Absolute for TimeOf<T> where T : Absolute
74{
75    fn abs(self) -> Self { TimeOf::from_s(self.second.abs()) }
76}
77
78impl<T:FloatingNumber> TimeOf<T>
79{
80    const fn from_internal_unit(internal_unit : T) -> Self { Self { second : internal_unit } }
81
82    /// milliseconds
83    /// ```
84    /// use hexga_math::*;
85    /// debug_assert_eq!(1000.ms(), 1.s());
86    /// ```
87    pub fn from_ms (ms : T) -> Self  { Self::from_s(ms / T::THOUSAND) }
88
89    /// milliseconds
90    /// ```
91    /// use hexga_math::*;
92    /// debug_assert_eq!(1.s().ms(), 1000.);
93    /// ```
94    pub fn ms(self) -> T { self.second * T::THOUSAND }
95
96
97    /// whole milliseconds
98    /// ```
99    /// use hexga_math::*;
100    /// debug_assert_eq!(0.5.ms().whole_ms(), 0);
101    /// debug_assert_eq!(1.0.ms().whole_ms(), 1);
102    /// debug_assert_eq!(1.5.ms().whole_ms(), 1);
103    /// debug_assert_eq!(1.9.ms().whole_ms(), 1);
104    /// debug_assert_eq!(2.0.ms().whole_ms(), 2);
105    /// 
106    /// debug_assert_eq!(-0.5.ms().whole_ms(),  0);
107    /// debug_assert_eq!(-2.0.ms().whole_ms(), -2);
108    /// debug_assert_eq!(-1.9.ms().whole_ms(), -1);
109    /// ```
110    pub fn whole_ms(self) -> i32 { self.ms().round_toward_zero().to_i32() }
111
112    /// Can be used to display milliseconds in a timer
113    /// ```
114    /// use hexga_math::*;
115    /// debug_assert_eq!(10.5.ms().timer_ms(), 10);
116    /// 
117    /// debug_assert_eq!(999.ms().timer_ms(), 999);
118    /// debug_assert_eq!(1000.ms().timer_ms(), 0);
119    /// debug_assert_eq!(1001.ms().timer_ms(), 1);
120    /// debug_assert_eq!(2005.ms().timer_ms(), 5);
121    /// ```
122    pub fn timer_ms(self) -> i32 { self.ms().abs().floor().to_i32() % 1000 }
123
124    /// seconds
125    /// ```
126    /// use hexga_math::*;
127    /// debug_assert_eq!(60.s(), 1.mins());
128    /// ```
129    pub const fn from_s(second : T) -> Self { Self::from_internal_unit(second) }
130
131    /// total seconds
132    /// ```
133    /// use hexga_math::*;
134    /// debug_assert_eq!(1.mins().s(), 60.);
135    /// ```
136    pub fn s(self) -> T { self.second }
137
138    /// whole seconds
139    /// ```
140    /// use hexga_math::*;
141    /// debug_assert_eq!(0.5.s().whole_s(), 0);
142    /// debug_assert_eq!(1.0.s().whole_s(), 1);
143    /// debug_assert_eq!(1.5.s().whole_s(), 1);
144    /// debug_assert_eq!(1.9.s().whole_s(), 1);
145    /// debug_assert_eq!(2.0.s().whole_s(), 2);
146    /// ```
147    pub fn whole_s(self) -> i32 { self.s().round_toward_zero().to_i32() }
148
149    /// Can be used to display seconds in a timer
150    /// 
151    /// ```
152    /// use hexga_math::*;
153    /// debug_assert_eq!(10.5.s().timer_s(), 10);
154    /// 
155    /// debug_assert_eq!(59.s().timer_s(), 59);
156    /// debug_assert_eq!(60.s().timer_s(), 0);
157    /// debug_assert_eq!(61.s().timer_s(), 1);
158    /// debug_assert_eq!(125.s().timer_s(), 5);
159    /// ```
160    pub fn timer_s(self) -> i32 { self.s().abs().floor().to_i32() % 60 }
161
162    /// minutes
163    /// ```
164    /// use hexga_math::*;
165    /// debug_assert_eq!(60.mins(), 1.hour());
166    /// ```
167    pub fn from_mins(min : T) -> Self { Self::from_s(min * T::SIXTY) }
168
169    /// minutes
170    /// ```
171    /// use hexga_math::*;
172    /// debug_assert_eq!(1.hour().mins(), 60.);
173    /// ```
174    pub fn mins(self) -> T { self.second / T::SIXTY }
175
176    /// whole minutes
177    /// ```
178    /// use hexga_math::*;
179    /// debug_assert_eq!(0.5.mins().whole_mins(), 0);
180    /// debug_assert_eq!(1.0.mins().whole_mins(), 1);
181    /// debug_assert_eq!(1.5.mins().whole_mins(), 1);
182    /// debug_assert_eq!(1.9.mins().whole_mins(), 1);
183    /// debug_assert_eq!(2.0.mins().whole_mins(), 2);
184    /// 
185    /// debug_assert_eq!(-0.5.mins().whole_mins(),  0);
186    /// debug_assert_eq!(-2.0.mins().whole_mins(), -2);
187    /// debug_assert_eq!(-1.9.mins().whole_mins(), -1);
188    /// ```
189    pub fn whole_mins(self) -> i32 { self.mins().round_toward_zero().to_i32() }
190
191
192    /// Can be used to display mins in a timer
193    /// ```
194    /// use hexga_math::*;
195    /// debug_assert_eq!(10.5.mins().timer_mins(), 10);
196    /// 
197    /// debug_assert_eq!(59.mins().timer_mins(), 59);
198    /// debug_assert_eq!(60.mins().timer_mins(), 0);
199    /// debug_assert_eq!(61.mins().timer_mins(), 1);
200    /// debug_assert_eq!(125.mins().timer_mins(), 5);
201    /// ```
202    pub fn timer_mins(self) -> i32 { self.mins().abs().floor().to_i32() % 60 }
203
204    /// hours
205    /// ```
206    /// use hexga_math::*;
207    /// debug_assert_eq!(24.hour(), 1.day());
208    /// ```
209    pub fn from_hour(hours : T) -> Self { Self::from_s(hours * (T::SIXTY * T::SIXTY)) }
210    /// hours
211    /// ```
212    /// use hexga_math::*;
213    /// debug_assert_eq!(1.day().hour(), 24.);
214    /// ```
215    pub fn hour(self) -> T { self.second / (T::SIXTY * T::SIXTY) }
216
217
218    /// ```
219    /// use hexga_math::*;
220    /// debug_assert_eq!(0.5.hour().whole_hour(), 0);
221    /// debug_assert_eq!(1.0.hour().whole_hour(), 1);
222    /// debug_assert_eq!(1.5.hour().whole_hour(), 1);
223    /// debug_assert_eq!(1.9.hour().whole_hour(), 1);
224    /// debug_assert_eq!(2.0.hour().whole_hour(), 2);
225    /// 
226    /// debug_assert_eq!(-0.5.hour().whole_hour(),  0);
227    /// debug_assert_eq!(-2.0.hour().whole_hour(), -2);
228    /// debug_assert_eq!(-1.9.hour().whole_hour(), -1);
229    /// ```
230    pub fn whole_hour(self) -> i32 { self.hour().round_toward_zero().to_i32() }
231
232
233    /// Can be used to display hours in a timer
234    /// ```
235    /// use hexga_math::*;
236    /// debug_assert_eq!(10.5.hour().timer_hour(), 10);
237    /// 
238    /// debug_assert_eq!(23.hour().timer_hour(), 23);
239    /// debug_assert_eq!(24.hour().timer_hour(), 0);
240    /// debug_assert_eq!(25.hour().timer_hour(), 1);
241    /// debug_assert_eq!((48+5).hour().timer_hour(), 5);
242    /// ```
243    pub fn timer_hour(self) -> i32 { self.hour().abs().floor().to_i32() % 24 }
244
245    /// days
246    /// ```
247    /// use hexga_math::*;
248    /// debug_assert_eq!(1.day(), (3600*24).s());
249    /// ```
250    pub fn from_day(day : T) -> Self { Self::from_s(day * (T::SIXTY * T::SIXTY * T::TWENTY_FOUR)) }
251    /// days
252    /// ```
253    /// use hexga_math::*;
254    /// debug_assert_eq!(24.hour().day(), 1.);
255    /// ```
256    pub fn day(self) -> T { self.second / (T::SIXTY * T::SIXTY * T::TWENTY_FOUR) }
257    /// Whole days
258    /// ```
259    /// use hexga_math::*;
260    /// debug_assert_eq!(0.5.day().whole_day(), 0);
261    /// debug_assert_eq!(1.0.day().whole_day(), 1);
262    /// debug_assert_eq!(1.5.day().whole_day(), 1);
263    /// debug_assert_eq!(1.9.day().whole_day(), 1);
264    /// debug_assert_eq!(2.0.day().whole_day(), 2);
265    /// 
266    /// debug_assert_eq!(-0.5.day().whole_day(),  0);
267    /// debug_assert_eq!(-2.0.day().whole_day(), -2);
268    /// debug_assert_eq!(-1.9.day().whole_day(), -1);
269    /// ```
270    pub fn whole_day(self) -> i32 { self.day().round_toward_zero().to_i32() }
271
272
273    /// Can be used to display days in a timer
274    /// ```
275    /// use hexga_math::*;
276    /// debug_assert_eq!(10.5.day().timer_day(), 10);
277    /// 
278    /// debug_assert_eq!(364.day().timer_day(), 364);
279    /// debug_assert_eq!(365.day().timer_day(), 365);
280    /// debug_assert_eq!(366.day().timer_day(), 366);
281    /// debug_assert_eq!(900.day().timer_day(), 900);
282    /// ```
283    pub fn timer_day(self) -> i32 { self.day().abs().floor().to_i32() }
284}
285
286impl<T:FloatingNumber> Add<TimeOf<T>> for TimeOf<T> { type Output=Self; fn add(self, rhs: Self) -> Self::Output { Self::from_internal_unit(self.second.add(rhs.second)) }}
287impl<T:FloatingNumber> AddAssign<TimeOf<T>> for TimeOf<T> { fn add_assign(&mut self, rhs: Self) { self.second.add_assign(rhs.second); }}
288
289impl<T:FloatingNumber> Sub<TimeOf<T>> for TimeOf<T> { type Output=Self; fn sub(self, rhs: Self) -> Self::Output { Self::from_internal_unit(self.second.sub(rhs.second)) }}
290impl<T:FloatingNumber> SubAssign<TimeOf<T>> for TimeOf<T> { fn sub_assign(&mut self, rhs: Self) { self.second.sub_assign(rhs.second); }}
291
292impl<T:FloatingNumber> Div<TimeOf<T>> for TimeOf<T> { type Output=T; fn div(self, rhs: Self) -> Self::Output { self.second / rhs.second } }
293impl<T:FloatingNumber> DivAssign<T> for TimeOf<T> { fn div_assign(&mut self, rhs: T) { self.second.div_assign(rhs) }}
294
295impl<T:FloatingNumber> Mul<T> for TimeOf<T> { type Output=Self; fn mul(self, rhs: T) -> Self::Output { Self::from_internal_unit(self.second.mul(rhs)) }}
296impl<T:FloatingNumber> MulAssign<T> for TimeOf<T> { fn mul_assign(&mut self, rhs: T) { self.second.mul_assign(rhs); }}
297
298impl<T:FloatingNumber> Div<T> for TimeOf<T> { type Output=TimeOf<T>; fn div(self, rhs: T) -> Self::Output { Self::from_internal_unit(self.second.div(rhs)) } }
299impl<T:FloatingNumber> Rem<T> for TimeOf<T> { type Output=TimeOf<T>; fn rem(self, rhs: T) -> Self::Output { Self::from_internal_unit(self.second.rem(rhs)) } }
300impl<T:FloatingNumber> RemAssign<T> for TimeOf<T> { fn rem_assign(&mut self, rhs: T) { self.second.rem_assign(rhs); } }
301
302impl<T:FloatingNumber> Sum for TimeOf<T>
303{
304    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
305        iter.fold(Self::ZERO, Self::add)
306    }
307}
308
309impl<T:FloatingNumber> MinValue for TimeOf<T> where T : MinValue
310{
311    const MIN : Self = Self::from_s(T::MIN);
312}
313
314impl<T:FloatingNumber> MaxValue for TimeOf<T> where T : MaxValue
315{
316    const MAX : Self = Self::from_s(T::MAX);
317}
318
319
320
321
322#[cfg(feature = "serde")]
323impl<T: FloatingNumber> Serialize for TimeOf<T> where T : Serialize {
324    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,
325    { self.s().serialize(serializer) }
326}
327
328#[cfg(feature = "serde")]
329impl<'de, T: FloatingNumber> Deserialize<'de> for TimeOf<T> where T : Deserialize<'de> {
330    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,
331    {
332        Ok(Self::from_s(T::deserialize(deserializer)?))
333    }
334}