@@ -8,6 +8,8 @@ use core::{
88
99use  super :: { pair_and_then,  TryFromTimeError } ; 
1010
11+ const  NANOS_PER_SEC :  u32  = 1_000_000_000 ; 
12+ 
1113/// A `Duration` type to represent a span of time, typically used for system 
1214/// timeouts. 
1315/// 
@@ -28,7 +30,6 @@ pub struct Duration(pub(crate) Option<time::Duration>);
2830impl  Duration  { 
2931    // TODO: duration_constants https://github.com/rust-lang/rust/issues/57391 
3032    // TODO: duration_zero https://github.com/rust-lang/rust/issues/73544 
31-     // TODO: duration_float https://github.com/rust-lang/rust/issues/54361 
3233    // TODO: div_duration https://github.com/rust-lang/rust/issues/63139 
3334
3435    /// Creates a new `Duration` from the specified number of whole seconds and 
@@ -39,7 +40,7 @@ impl Duration {
3940     #[ inline]  
4041    pub  fn  new ( secs :  u64 ,  nanos :  u32 )  -> Self  { 
4142        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 ) ; 
4344        Self ( secs. checked_add ( nanos) ) 
4445    } 
4546
@@ -154,6 +155,174 @@ impl Duration {
154155        } 
155156    } 
156157
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+ 
157326    // ============================================================================= 
158327    // Option based method implementations 
159328
0 commit comments