Skip to main content

deep_time/dt/
numbers_traits.rs

1//! Ergonomic time-unit constructors (optional import).
2//!
3//! ```
4//! use deep_time::{Scale, TraitsTime};
5//!
6//! let span = 5.sec() + 250.ms() + 123_456.ns();
7//! let stamp = 3.days().before_zero(Scale::UTC);
8//!
9//! // Wall-clock relative (requires the `std` feature):
10//! // let past = 3.days().ago();
11//! // let future = 3.days().from_now();
12//! ```
13
14use crate::{Dt, SEC_PER_DAY, SEC_PER_DAY_F, Scale};
15
16/// Trait that adds ergonomic time-unit methods to integers and floats.
17///
18/// ## Examples
19///
20/// ```rust
21/// use deep_time::TraitsTime;
22///
23/// let dt = 500.ns();
24/// let dt = 500.us();
25/// let dt = 500.ms();
26/// let dt = 30.sec();
27/// let dt = 30.mins();
28/// let dt = 2.hours();
29/// let dt = 5.days();
30/// let dt = 4.weeks();
31/// let dt = 10.years();
32/// ```
33pub trait TraitsTime: Copy + Sized {
34    fn ns(self) -> Dt;
35    fn us(self) -> Dt;
36    fn ms(self) -> Dt;
37    fn sec(self) -> Dt;
38    fn mins(self) -> Dt;
39    fn hours(self) -> Dt;
40    fn days(self) -> Dt; // 86400 s (civil day, not leap-second aware)
41    fn weeks(self) -> Dt;
42    fn years(self) -> Dt; // 365.25 days (standard approximation)
43}
44
45// Integer implementations (all common signed/unsigned types)
46macro_rules! impl_time_units_int {
47    ($($ty:ty),* $(,)?) => {
48        $(
49            impl TraitsTime for $ty {
50                #[inline]
51                fn ns(self) -> Dt { Dt::from_ns(self as i128, 0, Scale::TAI, Scale::TAI) }
52
53                #[inline]
54                fn us(self) -> Dt { Dt::from_us(self as i128, 0, Scale::TAI, Scale::TAI) }
55
56                #[inline]
57                fn ms(self) -> Dt { Dt::from_ms(self as i128, 0, Scale::TAI, Scale::TAI) }
58
59                #[inline]
60                fn sec(self) -> Dt { Dt::from_sec(self as i128, Scale::TAI, Scale::TAI) }
61
62                #[inline]
63                fn mins(self) -> Dt { Dt::from_mins(self as i128, 0, Scale::TAI, Scale::TAI) }
64
65                #[inline]
66                fn hours(self) -> Dt { Dt::from_hours(self as i128, 0, Scale::TAI, Scale::TAI) }
67
68                #[inline]
69                fn days(self) -> Dt { Dt::from_sec((self as i128).saturating_mul(SEC_PER_DAY), Scale::TAI, Scale::TAI) }
70
71                #[inline]
72                fn weeks(self) -> Dt { Dt::from_sec((self  as i128).saturating_mul(604_800), Scale::TAI, Scale::TAI) }
73
74                #[inline]
75                fn years(self) -> Dt { Dt::from_sec((self  as i128).saturating_mul(31_557_600), Scale::TAI, Scale::TAI) }
76            }
77        )*
78    };
79}
80
81impl_time_units_int!(i8, i16, i32, i64, i128, u8, u16, u32, u64);
82
83// `u128` alone among the integer impls can exceed `i128::MAX`; saturate instead of wrapping.
84impl TraitsTime for u128 {
85    #[inline]
86    fn ns(self) -> Dt {
87        Dt::from_ns(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
88    }
89
90    #[inline]
91    fn us(self) -> Dt {
92        Dt::from_us(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
93    }
94
95    #[inline]
96    fn ms(self) -> Dt {
97        Dt::from_ms(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
98    }
99
100    #[inline]
101    fn sec(self) -> Dt {
102        Dt::from_sec(Dt::to_i128(self), Scale::TAI, Scale::TAI)
103    }
104
105    #[inline]
106    fn mins(self) -> Dt {
107        Dt::from_mins(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
108    }
109
110    #[inline]
111    fn hours(self) -> Dt {
112        Dt::from_hours(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
113    }
114
115    #[inline]
116    fn days(self) -> Dt {
117        Dt::from_sec(
118            Dt::to_i128(self).saturating_mul(SEC_PER_DAY),
119            Scale::TAI,
120            Scale::TAI,
121        )
122    }
123
124    #[inline]
125    fn weeks(self) -> Dt {
126        Dt::from_sec(
127            Dt::to_i128(self).saturating_mul(604_800),
128            Scale::TAI,
129            Scale::TAI,
130        )
131    }
132
133    #[inline]
134    fn years(self) -> Dt {
135        Dt::from_sec(
136            Dt::to_i128(self).saturating_mul(31_557_600),
137            Scale::TAI,
138            Scale::TAI,
139        )
140    }
141}
142
143impl TraitsTime for f64 {
144    #[inline]
145    fn ns(self) -> Dt {
146        crate::macros::from_sec_f!(self * 1e-9)
147    }
148
149    #[inline]
150    fn us(self) -> Dt {
151        crate::macros::from_sec_f!(self * 1e-6)
152    }
153
154    #[inline]
155    fn ms(self) -> Dt {
156        crate::macros::from_sec_f!(self * 1e-3)
157    }
158
159    #[inline]
160    fn sec(self) -> Dt {
161        crate::macros::from_sec_f!(self)
162    }
163
164    #[inline]
165    fn mins(self) -> Dt {
166        (self * 60.0).sec()
167    }
168
169    #[inline]
170    fn hours(self) -> Dt {
171        (self * 3600.0).sec()
172    }
173
174    #[inline]
175    fn days(self) -> Dt {
176        (self * SEC_PER_DAY_F).sec()
177    }
178
179    #[inline]
180    fn weeks(self) -> Dt {
181        (self * 604_800.0).sec()
182    }
183
184    #[inline]
185    fn years(self) -> Dt {
186        (self * 31_557_600.0).sec()
187    }
188}
189
190impl TraitsTime for f32 {
191    #[inline]
192    fn ns(self) -> Dt {
193        crate::macros::from_sec_f!(self as f64 * 1e-9)
194    }
195
196    #[inline]
197    fn us(self) -> Dt {
198        crate::macros::from_sec_f!(self as f64 * 1e-6)
199    }
200
201    #[inline]
202    fn ms(self) -> Dt {
203        crate::macros::from_sec_f!(self as f64 * 1e-3)
204    }
205
206    #[inline]
207    fn sec(self) -> Dt {
208        crate::macros::from_sec_f!(self as f64)
209    }
210
211    #[inline]
212    fn mins(self) -> Dt {
213        (self * 60.0f32).sec()
214    }
215
216    #[inline]
217    fn hours(self) -> Dt {
218        (self * 3600.0f32).sec()
219    }
220
221    #[inline]
222    fn days(self) -> Dt {
223        (self * SEC_PER_DAY as f32).sec()
224    }
225
226    #[inline]
227    fn weeks(self) -> Dt {
228        (self * 604_800.0f32).sec()
229    }
230
231    #[inline]
232    fn years(self) -> Dt {
233        (self * 31_557_600.0f32).sec()
234    }
235}