Skip to main content

frclib_core/units/
time.rs

1use std::{ops::Neg, time::Duration};
2
3use crate::{unit, unit_conversion, unit_family};
4
5unit!(Hour: float);
6unit!(Minute: float);
7unit!(Second: float);
8unit!(Millisecond: float);
9unit!(Microsecond: uint);
10
11unit_conversion!(Second(float) <-> Millisecond(float) ~ second_to_millisecond);
12unit_conversion!(Second(float) <-> Microsecond(uint) ~ second_to_microsecond);
13unit_conversion!(Millisecond(float) <-> Microsecond(uint) ~ millisecond_to_microsecond);
14unit_conversion!(Hour(float) <-> Second(float) ~ hour_to_second);
15unit_conversion!(Minute(float) <-> Second(float) ~ minute_to_second);
16unit_conversion!(Hour(float) <-> Minute(float) ~ hour_to_minute);
17unit_conversion!(Minute(float) <-> Millisecond(float) ~ minute_to_millisecond);
18unit_conversion!(Minute(float) <-> Microsecond(uint) ~ minute_to_microsecond);
19unit_conversion!(Hour(float) <-> Millisecond(float) ~ hour_to_millisecond);
20unit_conversion!(Hour(float) <-> Microsecond(uint) ~ hour_to_microsecond);
21
22//TODO: This is a hack to satisfy unit family
23impl Neg for Microsecond {
24    type Output = Millisecond;
25    #[allow(clippy::cast_precision_loss)]
26    fn neg(self) -> Self::Output {
27        Millisecond::new(-(self.value() as f64))
28    }
29}
30
31unit_family!(Time(Second): Hour, Minute, Millisecond, Microsecond);
32
33fn second_to_millisecond(second: f64) -> f64 {
34    second * 1000.0
35}
36
37#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
38fn second_to_microsecond(second: f64) -> u64 {
39    if second.is_sign_negative() {
40        0
41    } else {
42        (second * 1_000_000.0) as u64
43    }
44}
45
46#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
47fn millisecond_to_microsecond(millisecond: f64) -> u64 {
48    if millisecond.is_sign_negative() {
49        0
50    } else {
51        (millisecond * 1000.0) as u64
52    }
53}
54
55fn hour_to_second(hour: f64) -> f64 {
56    hour * 3600.0
57}
58
59fn minute_to_second(minute: f64) -> f64 {
60    minute * 60.0
61}
62
63fn hour_to_minute(hour: f64) -> f64 {
64    hour * 60.0
65}
66
67fn minute_to_millisecond(minute: f64) -> f64 {
68    minute * 60000.0
69}
70
71#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
72fn minute_to_microsecond(minute: f64) -> u64 {
73    if minute.is_sign_negative() {
74        0
75    } else {
76        (minute * 60_000_000.0) as u64
77    }
78}
79
80fn hour_to_millisecond(hour: f64) -> f64 {
81    second_to_millisecond(hour_to_second(hour))
82}
83
84fn hour_to_microsecond(hour: f64) -> u64 {
85    second_to_microsecond(hour_to_second(hour))
86}
87
88impl From<Duration> for Hour {
89    fn from(duration: Duration) -> Self {
90        Self::new(duration.as_secs_f64() / 3600.0)
91    }
92}
93
94impl From<Duration> for Minute {
95    fn from(duration: Duration) -> Self {
96        Self::new(duration.as_secs_f64() / 60.0)
97    }
98}
99
100impl From<Duration> for Second {
101    fn from(duration: Duration) -> Self {
102        Self::new(duration.as_secs_f64())
103    }
104}
105
106impl From<Duration> for Millisecond {
107    fn from(duration: Duration) -> Self {
108        Self::new(duration.as_secs_f64() * 1000.0)
109    }
110}
111
112impl From<Duration> for Microsecond {
113    fn from(duration: Duration) -> Self {
114        Self::new(u64::try_from(duration.as_micros()).unwrap_or(u64::MAX))
115    }
116}
117
118impl From<Hour> for Duration {
119    fn from(hour: Hour) -> Self {
120        Self::from_secs_f64(hour.value() * 3600.0)
121    }
122}
123
124impl From<Minute> for Duration {
125    fn from(minute: Minute) -> Self {
126        Self::from_secs_f64(minute.value() * 60.0)
127    }
128}
129
130impl From<Second> for Duration {
131    fn from(second: Second) -> Self {
132        Self::from_secs_f64(second.value())
133    }
134}
135
136impl From<Millisecond> for Duration {
137    fn from(millisecond: Millisecond) -> Self {
138        Self::from_secs_f64(millisecond.value() / 1000.0)
139    }
140}
141
142impl From<Microsecond> for Duration {
143    fn from(microsecond: Microsecond) -> Self {
144        Self::from_micros(microsecond.value())
145    }
146}