diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 0fb5c0bac7562..41330bbb3d94a 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -1,5 +1,4 @@ #![stable(feature = "duration_core", since = "1.25.0")] - //! Temporal quantification. //! //! # Examples: @@ -308,6 +307,39 @@ impl Duration { Duration { secs, nanos: subsec_nanos } } + /// Creates a new Duration from the specified number of nanoseconds. + /// + /// # Panics + /// + /// Panics if the given number of nanoseconds is greater than what Duration can handle, + /// which is `(u64::MAX * NANOS_PER_SEC) + NANOS_PER_SEC - 1` + /// Use this function if you need to specify time greater than what can fit in u64 + /// (around 584 years). + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_from_nanos_u128)] + /// use std::time::Duration; + /// let time_in_nanos = 2u128.pow(64); + /// let duration = Duration::from_nanos_u128(time_in_nanos); + /// ``` + #[unstable(feature = "duration_from_nanos_u128", issue = "139201")] + #[must_use] + #[inline] + pub const fn from_nanos_u128(nanos: u128) -> Duration { + const NANOS_PER_SEC: u128 = self::NANOS_PER_SEC as u128; + let secs: u128 = nanos / NANOS_PER_SEC; + if secs > u64::MAX as u128 { + panic!("overflow in duration in Duration::from_nanos_u128"); + } + let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; + // SAFETY: x % 1_000_000_000 < 1_000_000_000 also, subsec_nanos >= 0 since u128 >=0 and u32 >=0 + let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) }; + + Duration { secs: secs as u64, nanos: subsec_nanos } + } + /// Creates a new `Duration` from the specified number of weeks. /// /// # Panics diff --git a/library/coretests/tests/time.rs b/library/coretests/tests/time.rs index bb98e59bf5a2b..b95c2c45f90ba 100644 --- a/library/coretests/tests/time.rs +++ b/library/coretests/tests/time.rs @@ -45,6 +45,15 @@ fn from_weeks_overflow() { let _ = Duration::from_weeks(overflow); } +#[test] +#[should_panic] +fn from_nanos_u128_overflow() { + let overflow = (u64::MAX * NANOS_PER_SEC) + (NANOS_PER_SEC - 1) + 1 ; + let _ = Duration::from_nanos_u128(overflow); +} + +#[test] +fn constructors() { #[test] fn constructor_weeks() { assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60)); @@ -81,6 +90,8 @@ fn secs() { assert_eq!(Duration::from_micros(1_000_001).as_secs(), 1); assert_eq!(Duration::from_nanos(999_999_999).as_secs(), 0); assert_eq!(Duration::from_nanos(1_000_000_001).as_secs(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).as_secs(),0); + assert_eq!(Duration::from_nanos_u128(1_000_000_001).as_secs(),1); } #[test] @@ -95,6 +106,8 @@ fn millis() { assert_eq!(Duration::from_micros(1_001_000).subsec_millis(), 1); assert_eq!(Duration::from_nanos(999_999_999).subsec_millis(), 999); assert_eq!(Duration::from_nanos(1_001_000_000).subsec_millis(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_millis(),999); + assert_eq!(Duration::from_nanos_u128(1_001_000_001).subsec_millis(),1); } #[test] @@ -109,6 +122,9 @@ fn micros() { assert_eq!(Duration::from_micros(1_000_001).subsec_micros(), 1); assert_eq!(Duration::from_nanos(999_999_999).subsec_micros(), 999_999); assert_eq!(Duration::from_nanos(1_000_001_000).subsec_micros(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_micros(),999_999); + assert_eq!(Duration::from_nanos_u128(1_000_001_000).subsec_micros(),1); + } #[test] @@ -123,6 +139,8 @@ fn nanos() { assert_eq!(Duration::from_micros(1_000_001).subsec_nanos(), 1000); assert_eq!(Duration::from_nanos(999_999_999).subsec_nanos(), 999_999_999); assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_nanos(),999_999_999); + assert_eq!(Duration::from_nanos_u128(1_000_000_001).subsec_nanos(),1); } #[test]