From a9eff4803149be045e388cf1ec1d8fb355840b57 Mon Sep 17 00:00:00 2001 From: omanirudh Date: Wed, 2 Apr 2025 11:55:55 +0530 Subject: [PATCH 1/3] Add from_nanos_u128 to Duration for handling large time spans Add unstable attribute Add unstable attribute for `from_nanos_u128` with tracking issue #139201 Co-authored-by: Madhav Madhusoodanan add feature gate for the new function - add feature gate - remove trailing whitespace Add feature gate at the right place Co-authored-by: Madhav Madhusoodanan Update time.rs making sure seconds are in u64 Co-authored-by: Madhav Madhusoodanan Update time.rs keeping seconds as u64 removing the use of non const function within const function Use a u128 example time.rs Earlier for the example I used 2.pow(64). correcting it to use u128 type which can contain the value Synched my fork Dummy commit dummy commit. sync local with fork style: format code with rustfmt Add panic test for Duration::from_nanos_u128 fix: remove non-const .into() call from const function A const function cannot call non-const functions, so we remove the trailing .into() call and use raw literals instead. remove paratheses Add comment on largest input and explain safety assumption Ran Rust fmt again --- Cargo.lock | 6 +++--- library/core/src/time.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97a90a44a398e..8801828df387e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,7 +225,7 @@ dependencies = [ "memchr", "serde", "serde_derive", - "winnow 0.7.4", + "winnow 0.7.6", ] [[package]] @@ -6415,9 +6415,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 18c03b4a6f89c..42b8bdbbeae0f 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 From ee100716292ca42f3d31cf2d14a4e89a7e96ab69 Mon Sep 17 00:00:00 2001 From: omanirudh Date: Mon, 21 Apr 2025 12:12:52 +0530 Subject: [PATCH 2/3] Removing changes to Cargo.lock checkout to previous commit git checkout 095486e12596281f9ab078af32becc348afb6dcb -- Cargo.lock --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8801828df387e..97a90a44a398e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,7 +225,7 @@ dependencies = [ "memchr", "serde", "serde_derive", - "winnow 0.7.6", + "winnow 0.7.4", ] [[package]] @@ -6415,9 +6415,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" dependencies = [ "memchr", ] From b7e27a428c6c8fa24a33b5f2c3658eb587665566 Mon Sep 17 00:00:00 2001 From: omanirudh Date: Sun, 29 Jun 2025 08:09:43 +0530 Subject: [PATCH 3/3] Tests for from_nanos_u128 method --- library/coretests/tests/time.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/coretests/tests/time.rs b/library/coretests/tests/time.rs index fe7bb11c67589..6040c0bbd2a9e 100644 --- a/library/coretests/tests/time.rs +++ b/library/coretests/tests/time.rs @@ -45,6 +45,13 @@ 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() { assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60)); @@ -72,6 +79,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] @@ -86,6 +95,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] @@ -100,6 +111,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] @@ -114,6 +128,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]