Skip to content

Commit a791919

Browse files
authored
Rollup merge of rust-lang#52813 - newpavlov:duration_mul_div_extras, r=alexcrichton
Duration div mul extras Successor of rust-lang#52556. This PR adds the following `impl`s: - `impl Mul<Duration> for u32` (to allow `10*SECOND` in addition to `SECOND*10`) - `impl Mul<f64> for Duration` (to allow `2.5*SECOND` vs `2*SECOND + 500*MILLISECOND`) - `impl Mul<Duration> for f64` - `impl MulAssign<f64> for Duration` - `impl Div<f64> for Duration` - `impl DivAssign<f64> for Duration` - `impl Div<Duration> for Duration` (`Output = f64`, can be useful e.g. for `duration/MINUTE`) `f64` is chosen over `f32` to minimize rounding errors. (52 bits fraction precision vs `Duration`'s ~94 bit)
2 parents f7f4c50 + fd7565b commit a791919

File tree

1 file changed

+120
-1
lines changed

1 file changed

+120
-1
lines changed

src/libcore/time.rs

+120-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
2222
//! ```
2323
24-
use fmt;
24+
use {fmt, u64};
2525
use iter::Sum;
2626
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
2727

@@ -30,6 +30,7 @@ const NANOS_PER_MILLI: u32 = 1_000_000;
3030
const NANOS_PER_MICRO: u32 = 1_000;
3131
const MILLIS_PER_SEC: u64 = 1_000;
3232
const MICROS_PER_SEC: u64 = 1_000_000;
33+
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
3334

3435
/// A `Duration` type to represent a span of time, typically used for system
3536
/// timeouts.
@@ -458,6 +459,115 @@ impl Duration {
458459
None
459460
}
460461
}
462+
463+
/// Returns the number of seconds contained by this `Duration` as `f64`.
464+
///
465+
/// The returned value does include the fractional (nanosecond) part of the duration.
466+
///
467+
/// # Examples
468+
/// ```
469+
/// #![feature(duration_float)]
470+
/// use std::time::Duration;
471+
///
472+
/// let dur = Duration::new(2, 700_000_000);
473+
/// assert_eq!(dur.as_float_secs(), 2.7);
474+
/// ```
475+
#[unstable(feature = "duration_float", issue = "54361")]
476+
#[inline]
477+
pub fn as_float_secs(&self) -> f64 {
478+
(self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
479+
}
480+
481+
/// Creates a new `Duration` from the specified number of seconds.
482+
///
483+
/// # Panics
484+
/// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
485+
///
486+
/// # Examples
487+
/// ```
488+
/// #![feature(duration_float)]
489+
/// use std::time::Duration;
490+
///
491+
/// let dur = Duration::from_float_secs(2.7);
492+
/// assert_eq!(dur, Duration::new(2, 700_000_000));
493+
/// ```
494+
#[unstable(feature = "duration_float", issue = "54361")]
495+
#[inline]
496+
pub fn from_float_secs(secs: f64) -> Duration {
497+
let nanos = secs * (NANOS_PER_SEC as f64);
498+
if !nanos.is_finite() {
499+
panic!("got non-finite value when converting float to duration");
500+
}
501+
if nanos >= MAX_NANOS_F64 {
502+
panic!("overflow when converting float to duration");
503+
}
504+
if nanos < 0.0 {
505+
panic!("underflow when converting float to duration");
506+
}
507+
let nanos = nanos as u128;
508+
Duration {
509+
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
510+
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
511+
}
512+
}
513+
514+
/// Multiply `Duration` by `f64`.
515+
///
516+
/// # Panics
517+
/// This method will panic if result is not finite, negative or overflows `Duration`.
518+
///
519+
/// # Examples
520+
/// ```
521+
/// #![feature(duration_float)]
522+
/// use std::time::Duration;
523+
///
524+
/// let dur = Duration::new(2, 700_000_000);
525+
/// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
526+
/// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
527+
/// ```
528+
#[unstable(feature = "duration_float", issue = "54361")]
529+
#[inline]
530+
pub fn mul_f64(self, rhs: f64) -> Duration {
531+
Duration::from_float_secs(rhs * self.as_float_secs())
532+
}
533+
534+
/// Divide `Duration` by `f64`.
535+
///
536+
/// # Panics
537+
/// This method will panic if result is not finite, negative or overflows `Duration`.
538+
///
539+
/// # Examples
540+
/// ```
541+
/// #![feature(duration_float)]
542+
/// use std::time::Duration;
543+
///
544+
/// let dur = Duration::new(2, 700_000_000);
545+
/// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
546+
/// // note that truncation is used, not rounding
547+
/// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
548+
/// ```
549+
#[unstable(feature = "duration_float", issue = "54361")]
550+
#[inline]
551+
pub fn div_f64(self, rhs: f64) -> Duration {
552+
Duration::from_float_secs(self.as_float_secs() / rhs)
553+
}
554+
555+
/// Divide `Duration` by `Duration` and return `f64`.
556+
///
557+
/// # Examples
558+
/// ```
559+
/// #![feature(duration_float)]
560+
/// use std::time::Duration;
561+
///
562+
/// let dur1 = Duration::new(2, 700_000_000);
563+
/// let dur2 = Duration::new(5, 400_000_000);
564+
/// assert_eq!(dur1.div_duration(dur2), 0.5);
565+
/// ```
566+
#[unstable(feature = "duration_float", issue = "54361")]
567+
#[inline]
568+
pub fn div_duration(self, rhs: Duration) -> f64 {
569+
self.as_float_secs() / rhs.as_float_secs()
570+
}
461571
}
462572

463573
#[stable(feature = "duration", since = "1.3.0")]
@@ -501,6 +611,15 @@ impl Mul<u32> for Duration {
501611
}
502612
}
503613

614+
#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")]
615+
impl Mul<Duration> for u32 {
616+
type Output = Duration;
617+
618+
fn mul(self, rhs: Duration) -> Duration {
619+
rhs * self
620+
}
621+
}
622+
504623
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
505624
impl MulAssign<u32> for Duration {
506625
fn mul_assign(&mut self, rhs: u32) {

0 commit comments

Comments
 (0)