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    /// Duration of `self` nanoseconds as a [`Dt`].
35    fn ns(self) -> Dt;
36    /// Duration of `self` microseconds as a [`Dt`].
37    fn us(self) -> Dt;
38    /// Duration of `self` milliseconds as a [`Dt`].
39    fn ms(self) -> Dt;
40    /// Duration of `self` seconds as a [`Dt`].
41    fn sec(self) -> Dt;
42    /// Duration of `self` minutes as a [`Dt`].
43    fn mins(self) -> Dt;
44    /// Duration of `self` hours as a [`Dt`].
45    fn hours(self) -> Dt;
46    /// Duration of `self` civil days (86 400 s each; not leap-second aware).
47    fn days(self) -> Dt;
48    /// Duration of `self` weeks (7 civil days each).
49    fn weeks(self) -> Dt;
50    /// Duration of `self` Julian years (365.25 civil days each).
51    fn years(self) -> Dt;
52}
53
54// Integer implementations (all common signed/unsigned types)
55macro_rules! impl_time_units_int {
56    ($($ty:ty),* $(,)?) => {
57        $(
58            impl TraitsTime for $ty {
59                #[inline]
60                fn ns(self) -> Dt { Dt::from_ns(self as i128, 0, Scale::TAI, Scale::TAI) }
61
62                #[inline]
63                fn us(self) -> Dt { Dt::from_us(self as i128, 0, Scale::TAI, Scale::TAI) }
64
65                #[inline]
66                fn ms(self) -> Dt { Dt::from_ms(self as i128, 0, Scale::TAI, Scale::TAI) }
67
68                #[inline]
69                fn sec(self) -> Dt { Dt::from_sec(self as i128, Scale::TAI, Scale::TAI) }
70
71                #[inline]
72                fn mins(self) -> Dt { Dt::from_mins(self as i128, 0, Scale::TAI, Scale::TAI) }
73
74                #[inline]
75                fn hours(self) -> Dt { Dt::from_hours(self as i128, 0, Scale::TAI, Scale::TAI) }
76
77                #[inline]
78                fn days(self) -> Dt { Dt::from_sec((self as i128).saturating_mul(SEC_PER_DAY), Scale::TAI, Scale::TAI) }
79
80                #[inline]
81                fn weeks(self) -> Dt { Dt::from_sec((self  as i128).saturating_mul(604_800), Scale::TAI, Scale::TAI) }
82
83                #[inline]
84                fn years(self) -> Dt { Dt::from_sec((self  as i128).saturating_mul(31_557_600), Scale::TAI, Scale::TAI) }
85            }
86        )*
87    };
88}
89
90impl_time_units_int!(i8, i16, i32, i64, i128, u8, u16, u32, u64);
91
92// `u128` alone among the integer impls can exceed `i128::MAX`; saturate instead of wrapping.
93impl TraitsTime for u128 {
94    #[inline]
95    fn ns(self) -> Dt {
96        Dt::from_ns(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
97    }
98
99    #[inline]
100    fn us(self) -> Dt {
101        Dt::from_us(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
102    }
103
104    #[inline]
105    fn ms(self) -> Dt {
106        Dt::from_ms(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
107    }
108
109    #[inline]
110    fn sec(self) -> Dt {
111        Dt::from_sec(Dt::to_i128(self), Scale::TAI, Scale::TAI)
112    }
113
114    #[inline]
115    fn mins(self) -> Dt {
116        Dt::from_mins(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
117    }
118
119    #[inline]
120    fn hours(self) -> Dt {
121        Dt::from_hours(Dt::to_i128(self), 0, Scale::TAI, Scale::TAI)
122    }
123
124    #[inline]
125    fn days(self) -> Dt {
126        Dt::from_sec(
127            Dt::to_i128(self).saturating_mul(SEC_PER_DAY),
128            Scale::TAI,
129            Scale::TAI,
130        )
131    }
132
133    #[inline]
134    fn weeks(self) -> Dt {
135        Dt::from_sec(
136            Dt::to_i128(self).saturating_mul(604_800),
137            Scale::TAI,
138            Scale::TAI,
139        )
140    }
141
142    #[inline]
143    fn years(self) -> Dt {
144        Dt::from_sec(
145            Dt::to_i128(self).saturating_mul(31_557_600),
146            Scale::TAI,
147            Scale::TAI,
148        )
149    }
150}
151
152impl TraitsTime for f64 {
153    #[inline]
154    fn ns(self) -> Dt {
155        crate::macros::from_sec_f!(self * 1e-9)
156    }
157
158    #[inline]
159    fn us(self) -> Dt {
160        crate::macros::from_sec_f!(self * 1e-6)
161    }
162
163    #[inline]
164    fn ms(self) -> Dt {
165        crate::macros::from_sec_f!(self * 1e-3)
166    }
167
168    #[inline]
169    fn sec(self) -> Dt {
170        crate::macros::from_sec_f!(self)
171    }
172
173    #[inline]
174    fn mins(self) -> Dt {
175        (self * 60.0).sec()
176    }
177
178    #[inline]
179    fn hours(self) -> Dt {
180        (self * 3600.0).sec()
181    }
182
183    #[inline]
184    fn days(self) -> Dt {
185        (self * SEC_PER_DAY_F).sec()
186    }
187
188    #[inline]
189    fn weeks(self) -> Dt {
190        (self * 604_800.0).sec()
191    }
192
193    #[inline]
194    fn years(self) -> Dt {
195        (self * 31_557_600.0).sec()
196    }
197}
198
199impl TraitsTime for f32 {
200    #[inline]
201    fn ns(self) -> Dt {
202        crate::macros::from_sec_f!(self as f64 * 1e-9)
203    }
204
205    #[inline]
206    fn us(self) -> Dt {
207        crate::macros::from_sec_f!(self as f64 * 1e-6)
208    }
209
210    #[inline]
211    fn ms(self) -> Dt {
212        crate::macros::from_sec_f!(self as f64 * 1e-3)
213    }
214
215    #[inline]
216    fn sec(self) -> Dt {
217        crate::macros::from_sec_f!(self as f64)
218    }
219
220    #[inline]
221    fn mins(self) -> Dt {
222        (self * 60.0f32).sec()
223    }
224
225    #[inline]
226    fn hours(self) -> Dt {
227        (self * 3600.0f32).sec()
228    }
229
230    #[inline]
231    fn days(self) -> Dt {
232        (self * SEC_PER_DAY as f32).sec()
233    }
234
235    #[inline]
236    fn weeks(self) -> Dt {
237        (self * 604_800.0f32).sec()
238    }
239
240    #[inline]
241    fn years(self) -> Dt {
242        (self * 31_557_600.0f32).sec()
243    }
244}