Skip to content

Commit 27d11bc

Browse files
brokemillenialtgross35
authored andcommitted
Add Duration::from_nanos_u128
Tracking issue: RUST-139201
1 parent 915a766 commit 27d11bc

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

library/core/src/time.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,39 @@ impl Duration {
308308
Duration { secs, nanos: subsec_nanos }
309309
}
310310

311+
/// Creates a new Duration from the specified number of nanoseconds.
312+
///
313+
/// # Panics
314+
///
315+
/// Panics if the given number of nanoseconds is greater than what Duration can handle,
316+
/// which is `(u64::MAX * NANOS_PER_SEC) + NANOS_PER_SEC - 1`
317+
/// Use this function if you need to specify time greater than what can fit in u64
318+
/// (around 584 years).
319+
///
320+
/// # Examples
321+
///
322+
/// ```
323+
/// #![feature(duration_from_nanos_u128)]
324+
/// use std::time::Duration;
325+
/// let time_in_nanos = 2u128.pow(64);
326+
/// let duration = Duration::from_nanos_u128(time_in_nanos);
327+
/// ```
328+
#[unstable(feature = "duration_from_nanos_u128", issue = "139201")]
329+
#[must_use]
330+
#[inline]
331+
pub const fn from_nanos_u128(nanos: u128) -> Duration {
332+
const NANOS_PER_SEC: u128 = self::NANOS_PER_SEC as u128;
333+
let secs: u128 = nanos / NANOS_PER_SEC;
334+
if secs > u64::MAX as u128 {
335+
panic!("overflow in duration in Duration::from_nanos_u128");
336+
}
337+
let subsec_nanos = (nanos % NANOS_PER_SEC) as u32;
338+
// SAFETY: x % 1_000_000_000 < 1_000_000_000 also, subsec_nanos >= 0 since u128 >=0 and u32 >=0
339+
let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) };
340+
341+
Duration { secs: secs as u64, nanos: subsec_nanos }
342+
}
343+
311344
/// Creates a new `Duration` from the specified number of weeks.
312345
///
313346
/// # Panics

library/coretests/tests/time.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ fn from_weeks_overflow() {
4545
let _ = Duration::from_weeks(overflow);
4646
}
4747

48+
#[test]
49+
#[should_panic]
50+
fn from_nanos_u128_overflow() {
51+
let overflow = (u64::MAX * NANOS_PER_SEC) + (NANOS_PER_SEC - 1) + 1;
52+
let _ = Duration::from_nanos_u128(overflow);
53+
}
54+
4855
#[test]
4956
fn constructor_weeks() {
5057
assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60));
@@ -81,6 +88,8 @@ fn secs() {
8188
assert_eq!(Duration::from_micros(1_000_001).as_secs(), 1);
8289
assert_eq!(Duration::from_nanos(999_999_999).as_secs(), 0);
8390
assert_eq!(Duration::from_nanos(1_000_000_001).as_secs(), 1);
91+
assert_eq!(Duration::from_nanos_u128(999_999_999).as_secs(), 0);
92+
assert_eq!(Duration::from_nanos_u128(1_000_000_001).as_secs(), 1);
8493
}
8594

8695
#[test]
@@ -95,6 +104,8 @@ fn millis() {
95104
assert_eq!(Duration::from_micros(1_001_000).subsec_millis(), 1);
96105
assert_eq!(Duration::from_nanos(999_999_999).subsec_millis(), 999);
97106
assert_eq!(Duration::from_nanos(1_001_000_000).subsec_millis(), 1);
107+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_millis(), 999);
108+
assert_eq!(Duration::from_nanos_u128(1_001_000_001).subsec_millis(), 1);
98109
}
99110

100111
#[test]
@@ -109,6 +120,8 @@ fn micros() {
109120
assert_eq!(Duration::from_micros(1_000_001).subsec_micros(), 1);
110121
assert_eq!(Duration::from_nanos(999_999_999).subsec_micros(), 999_999);
111122
assert_eq!(Duration::from_nanos(1_000_001_000).subsec_micros(), 1);
123+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_micros(), 999_999);
124+
assert_eq!(Duration::from_nanos_u128(1_000_001_000).subsec_micros(), 1);
112125
}
113126

114127
#[test]
@@ -123,6 +136,8 @@ fn nanos() {
123136
assert_eq!(Duration::from_micros(1_000_001).subsec_nanos(), 1000);
124137
assert_eq!(Duration::from_nanos(999_999_999).subsec_nanos(), 999_999_999);
125138
assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1);
139+
assert_eq!(Duration::from_nanos_u128(999_999_999).subsec_nanos(), 999_999_999);
140+
assert_eq!(Duration::from_nanos_u128(1_000_000_001).subsec_nanos(), 1);
126141
}
127142

128143
#[test]

0 commit comments

Comments
 (0)