1 | use core::time::Duration as StdDuration; |
2 | |
3 | use num_conv::prelude::*; |
4 | |
5 | use crate::convert::*; |
6 | |
7 | /// Sealed trait to prevent downstream implementations. |
8 | mod sealed { |
9 | /// A trait that cannot be implemented by downstream users. |
10 | pub trait Sealed {} |
11 | impl Sealed for u64 {} |
12 | impl Sealed for f64 {} |
13 | } |
14 | |
15 | /// Create [`std::time::Duration`]s from numeric literals. |
16 | /// |
17 | /// # Examples |
18 | /// |
19 | /// Basic construction of [`std::time::Duration`]s. |
20 | /// |
21 | /// ```rust |
22 | /// # use time::ext::NumericalStdDuration; |
23 | /// # use core::time::Duration; |
24 | /// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5)); |
25 | /// assert_eq!(5.std_microseconds(), Duration::from_micros(5)); |
26 | /// assert_eq!(5.std_milliseconds(), Duration::from_millis(5)); |
27 | /// assert_eq!(5.std_seconds(), Duration::from_secs(5)); |
28 | /// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60)); |
29 | /// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600)); |
30 | /// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400)); |
31 | /// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800)); |
32 | /// ``` |
33 | /// |
34 | /// Just like any other [`std::time::Duration`], they can be added, subtracted, etc. |
35 | /// |
36 | /// ```rust |
37 | /// # use time::ext::NumericalStdDuration; |
38 | /// assert_eq!( |
39 | /// 2.std_seconds() + 500.std_milliseconds(), |
40 | /// 2_500.std_milliseconds() |
41 | /// ); |
42 | /// assert_eq!( |
43 | /// 2.std_seconds() - 500.std_milliseconds(), |
44 | /// 1_500.std_milliseconds() |
45 | /// ); |
46 | /// ``` |
47 | /// |
48 | /// When called on floating point values, any remainder of the floating point value will be |
49 | /// truncated. Keep in mind that floating point numbers are inherently imprecise and have |
50 | /// limited capacity. |
51 | pub trait NumericalStdDuration: sealed::Sealed { |
52 | /// Create a [`std::time::Duration`] from the number of nanoseconds. |
53 | fn std_nanoseconds(self) -> StdDuration; |
54 | /// Create a [`std::time::Duration`] from the number of microseconds. |
55 | fn std_microseconds(self) -> StdDuration; |
56 | /// Create a [`std::time::Duration`] from the number of milliseconds. |
57 | fn std_milliseconds(self) -> StdDuration; |
58 | /// Create a [`std::time::Duration`] from the number of seconds. |
59 | fn std_seconds(self) -> StdDuration; |
60 | /// Create a [`std::time::Duration`] from the number of minutes. |
61 | fn std_minutes(self) -> StdDuration; |
62 | /// Create a [`std::time::Duration`] from the number of hours. |
63 | fn std_hours(self) -> StdDuration; |
64 | /// Create a [`std::time::Duration`] from the number of days. |
65 | fn std_days(self) -> StdDuration; |
66 | /// Create a [`std::time::Duration`] from the number of weeks. |
67 | fn std_weeks(self) -> StdDuration; |
68 | } |
69 | |
70 | impl NumericalStdDuration for u64 { |
71 | fn std_nanoseconds(self) -> StdDuration { |
72 | StdDuration::from_nanos(self) |
73 | } |
74 | |
75 | fn std_microseconds(self) -> StdDuration { |
76 | StdDuration::from_micros(self) |
77 | } |
78 | |
79 | fn std_milliseconds(self) -> StdDuration { |
80 | StdDuration::from_millis(self) |
81 | } |
82 | |
83 | fn std_seconds(self) -> StdDuration { |
84 | StdDuration::from_secs(self) |
85 | } |
86 | |
87 | /// # Panics |
88 | /// |
89 | /// This may panic if an overflow occurs. |
90 | fn std_minutes(self) -> StdDuration { |
91 | StdDuration::from_secs( |
92 | self.checked_mul(Second::per(Minute).extend()) |
93 | .expect("overflow constructing `time::Duration`" ), |
94 | ) |
95 | } |
96 | |
97 | /// # Panics |
98 | /// |
99 | /// This may panic if an overflow occurs. |
100 | fn std_hours(self) -> StdDuration { |
101 | StdDuration::from_secs( |
102 | self.checked_mul(Second::per(Hour).extend()) |
103 | .expect("overflow constructing `time::Duration`" ), |
104 | ) |
105 | } |
106 | |
107 | /// # Panics |
108 | /// |
109 | /// This may panic if an overflow occurs. |
110 | fn std_days(self) -> StdDuration { |
111 | StdDuration::from_secs( |
112 | self.checked_mul(Second::per(Day).extend()) |
113 | .expect("overflow constructing `time::Duration`" ), |
114 | ) |
115 | } |
116 | |
117 | /// # Panics |
118 | /// |
119 | /// This may panic if an overflow occurs. |
120 | fn std_weeks(self) -> StdDuration { |
121 | StdDuration::from_secs( |
122 | self.checked_mul(Second::per(Week).extend()) |
123 | .expect("overflow constructing `time::Duration`" ), |
124 | ) |
125 | } |
126 | } |
127 | |
128 | impl NumericalStdDuration for f64 { |
129 | /// # Panics |
130 | /// |
131 | /// This will panic if self is negative. |
132 | fn std_nanoseconds(self) -> StdDuration { |
133 | assert!(self >= 0.); |
134 | StdDuration::from_nanos(self as _) |
135 | } |
136 | |
137 | /// # Panics |
138 | /// |
139 | /// This will panic if self is negative. |
140 | fn std_microseconds(self) -> StdDuration { |
141 | assert!(self >= 0.); |
142 | StdDuration::from_nanos((self * Nanosecond::per(Microsecond) as Self) as _) |
143 | } |
144 | |
145 | /// # Panics |
146 | /// |
147 | /// This will panic if self is negative. |
148 | fn std_milliseconds(self) -> StdDuration { |
149 | assert!(self >= 0.); |
150 | StdDuration::from_nanos((self * Nanosecond::per(Millisecond) as Self) as _) |
151 | } |
152 | |
153 | /// # Panics |
154 | /// |
155 | /// This will panic if self is negative. |
156 | fn std_seconds(self) -> StdDuration { |
157 | assert!(self >= 0.); |
158 | StdDuration::from_nanos((self * Nanosecond::per(Second) as Self) as _) |
159 | } |
160 | |
161 | /// # Panics |
162 | /// |
163 | /// This will panic if self is negative. |
164 | fn std_minutes(self) -> StdDuration { |
165 | assert!(self >= 0.); |
166 | StdDuration::from_nanos((self * Nanosecond::per(Minute) as Self) as _) |
167 | } |
168 | |
169 | /// # Panics |
170 | /// |
171 | /// This will panic if self is negative. |
172 | fn std_hours(self) -> StdDuration { |
173 | assert!(self >= 0.); |
174 | StdDuration::from_nanos((self * Nanosecond::per(Hour) as Self) as _) |
175 | } |
176 | |
177 | /// # Panics |
178 | /// |
179 | /// This will panic if self is negative. |
180 | fn std_days(self) -> StdDuration { |
181 | assert!(self >= 0.); |
182 | StdDuration::from_nanos((self * Nanosecond::per(Day) as Self) as _) |
183 | } |
184 | |
185 | /// # Panics |
186 | /// |
187 | /// This will panic if self is negative. |
188 | fn std_weeks(self) -> StdDuration { |
189 | assert!(self >= 0.); |
190 | StdDuration::from_nanos((self * Nanosecond::per(Week) as Self) as _) |
191 | } |
192 | } |
193 | |