@@ -8,6 +8,8 @@ use core::{
8
8
9
9
use super :: { pair_and_then, TryFromTimeError } ;
10
10
11
+ const NANOS_PER_SEC : u32 = 1_000_000_000 ;
12
+
11
13
/// A `Duration` type to represent a span of time, typically used for system
12
14
/// timeouts.
13
15
///
@@ -28,7 +30,6 @@ pub struct Duration(pub(crate) Option<time::Duration>);
28
30
impl Duration {
29
31
// TODO: duration_constants https://github.com/rust-lang/rust/issues/57391
30
32
// TODO: duration_zero https://github.com/rust-lang/rust/issues/73544
31
- // TODO: duration_float https://github.com/rust-lang/rust/issues/54361
32
33
// TODO: div_duration https://github.com/rust-lang/rust/issues/63139
33
34
34
35
/// Creates a new `Duration` from the specified number of whole seconds and
@@ -39,7 +40,7 @@ impl Duration {
39
40
#[ inline]
40
41
pub fn new ( secs : u64 , nanos : u32 ) -> Self {
41
42
let secs = time:: Duration :: from_secs ( secs) ;
42
- let nanos = time:: Duration :: from_nanos ( u64 :: from ( nanos) ) ;
43
+ let nanos = time:: Duration :: from_nanos ( nanos as u64 ) ;
43
44
Self ( secs. checked_add ( nanos) )
44
45
}
45
46
@@ -154,6 +155,174 @@ impl Duration {
154
155
}
155
156
}
156
157
158
+ /// Returns the number of seconds contained by this `Duration` as `f64`.
159
+ ///
160
+ /// The returned value does include the fractional (nanosecond) part of the duration.
161
+ ///
162
+ /// # Examples
163
+ ///
164
+ /// ```
165
+ /// use easytime::Duration;
166
+ ///
167
+ /// let dur = Duration::new(2, 700_000_000);
168
+ /// assert_eq!(dur.as_secs_f64(), Some(2.7));
169
+ /// ```
170
+ #[ inline]
171
+ pub fn as_secs_f64 ( & self ) -> Option < f64 > {
172
+ // TODO: replace with `self.0.as_ref().map(time::Duration::as_secs_f64)` on Rust 1.38+.
173
+ self . 0 . map ( |this| {
174
+ ( this. as_secs ( ) as f64 ) + ( this. subsec_nanos ( ) as f64 ) / ( NANOS_PER_SEC as f64 )
175
+ } )
176
+ }
177
+
178
+ /// Returns the number of seconds contained by this `Duration` as `f32`.
179
+ ///
180
+ /// The returned value does include the fractional (nanosecond) part of the duration.
181
+ ///
182
+ /// # Examples
183
+ ///
184
+ /// ```
185
+ /// use easytime::Duration;
186
+ ///
187
+ /// let dur = Duration::new(2, 700_000_000);
188
+ /// assert_eq!(dur.as_secs_f32(), Some(2.7));
189
+ /// ```
190
+ #[ inline]
191
+ pub fn as_secs_f32 ( & self ) -> Option < f32 > {
192
+ // TODO: replace with `self.0.as_ref().map(time::Duration::as_secs_f32)` on Rust 1.38+.
193
+ self . 0 . map ( |this| {
194
+ ( this. as_secs ( ) as f32 ) + ( this. subsec_nanos ( ) as f32 ) / ( NANOS_PER_SEC as f32 )
195
+ } )
196
+ }
197
+
198
+ /// Creates a new `Duration` from the specified number of seconds represented
199
+ /// as `f64`.
200
+ ///
201
+ /// # Examples
202
+ ///
203
+ /// ```
204
+ /// use easytime::Duration;
205
+ ///
206
+ /// let dur = Duration::from_secs_f64(2.7);
207
+ /// assert_eq!(dur, Duration::new(2, 700_000_000));
208
+ /// ```
209
+ #[ inline]
210
+ pub fn from_secs_f64 ( secs : f64 ) -> Self {
211
+ const MAX_NANOS_F64 : f64 =
212
+ ( ( u64:: max_value ( ) as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f64 ;
213
+ let nanos = secs * ( NANOS_PER_SEC as f64 ) ;
214
+ if !nanos. is_finite ( ) || nanos >= MAX_NANOS_F64 || nanos < 0.0 {
215
+ return Self ( None ) ;
216
+ }
217
+ let nanos = nanos as u128 ;
218
+ Self :: new (
219
+ ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
220
+ ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
221
+ )
222
+ }
223
+
224
+ /// Creates a new `Duration` from the specified number of seconds represented
225
+ /// as `f32`.
226
+ ///
227
+ /// # Examples
228
+ ///
229
+ /// ```
230
+ /// use easytime::Duration;
231
+ ///
232
+ /// let dur = Duration::from_secs_f32(2.7);
233
+ /// assert_eq!(dur, Duration::new(2, 700_000_000));
234
+ /// ```
235
+ #[ inline]
236
+ pub fn from_secs_f32 ( secs : f32 ) -> Duration {
237
+ const MAX_NANOS_F32 : f32 =
238
+ ( ( u64:: max_value ( ) as u128 + 1 ) * ( NANOS_PER_SEC as u128 ) ) as f32 ;
239
+ let nanos = secs * ( NANOS_PER_SEC as f32 ) ;
240
+ if !nanos. is_finite ( ) || nanos >= MAX_NANOS_F32 || nanos < 0.0 {
241
+ return Self ( None ) ;
242
+ }
243
+ let nanos = nanos as u128 ;
244
+ Self :: new (
245
+ ( nanos / ( NANOS_PER_SEC as u128 ) ) as u64 ,
246
+ ( nanos % ( NANOS_PER_SEC as u128 ) ) as u32 ,
247
+ )
248
+ }
249
+
250
+ /// Multiplies `Duration` by `f64`.
251
+ ///
252
+ /// # Examples
253
+ ///
254
+ /// ```
255
+ /// use easytime::Duration;
256
+ ///
257
+ /// let dur = Duration::new(2, 700_000_000);
258
+ /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
259
+ /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
260
+ /// ```
261
+ #[ inline]
262
+ pub fn mul_f64 ( self , rhs : f64 ) -> Duration {
263
+ self . as_secs_f64 ( )
264
+ . map ( |secs| Duration :: from_secs_f64 ( rhs * secs) )
265
+ . unwrap_or_else ( || Self ( None ) )
266
+ }
267
+
268
+ /// Multiplies `Duration` by `f32`.
269
+ ///
270
+ /// # Examples
271
+ ///
272
+ /// ```
273
+ /// use easytime::Duration;
274
+ ///
275
+ /// let dur = Duration::new(2, 700_000_000);
276
+ /// // note that due to rounding errors result is slightly different
277
+ /// // from 8.478 and 847800.0
278
+ /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640));
279
+ /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847799, 969_120_256));
280
+ /// ```
281
+ #[ inline]
282
+ pub fn mul_f32 ( self , rhs : f32 ) -> Duration {
283
+ self . as_secs_f32 ( )
284
+ . map ( |secs| Duration :: from_secs_f32 ( rhs * secs) )
285
+ . unwrap_or_else ( || Self ( None ) )
286
+ }
287
+
288
+ /// Divide `Duration` by `f64`.
289
+ ///
290
+ /// # Examples
291
+ ///
292
+ /// ```
293
+ /// use easytime::Duration;
294
+ ///
295
+ /// let dur = Duration::new(2, 700_000_000);
296
+ /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
297
+ /// // note that truncation is used, not rounding
298
+ /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
299
+ /// ```
300
+ #[ inline]
301
+ pub fn div_f64 ( self , rhs : f64 ) -> Duration {
302
+ self . as_secs_f64 ( )
303
+ . map ( |secs| Duration :: from_secs_f64 ( secs / rhs) )
304
+ . unwrap_or_else ( || Self ( None ) )
305
+ }
306
+
307
+ /// Divide `Duration` by `f32`.
308
+ ///
309
+ /// # Examples
310
+ ///
311
+ /// ```
312
+ /// use easytime::Duration;
313
+ ///
314
+ /// let dur = Duration::new(2, 700_000_000);
315
+ /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
316
+ /// // note that truncation is used, not rounding
317
+ /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
318
+ /// ```
319
+ #[ inline]
320
+ pub fn div_f32 ( self , rhs : f32 ) -> Duration {
321
+ self . as_secs_f32 ( )
322
+ . map ( |secs| Duration :: from_secs_f32 ( secs / rhs) )
323
+ . unwrap_or_else ( || Self ( None ) )
324
+ }
325
+
157
326
// =============================================================================
158
327
// Option based method implementations
159
328
0 commit comments