From e077ff0eedd600c1e8e1a556a520b456457b0312 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 24 Jan 2024 14:14:17 +0100 Subject: [PATCH] core: add Duration constructors --- library/core/src/time.rs | 120 ++++++++++++++++++ library/core/tests/lib.rs | 1 + library/core/tests/time.rs | 43 +++++++ .../library-features/duration-constructors.md | 9 ++ 4 files changed, 173 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/duration-constructors.md diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b677776443fe0..de976760e5545 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -28,6 +28,14 @@ const NANOS_PER_MILLI: u32 = 1_000_000; const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; const MICROS_PER_SEC: u64 = 1_000_000; +#[unstable(feature = "duration_units", issue = "120301")] +const SECS_PER_MINUTE: u64 = 60; +#[unstable(feature = "duration_units", issue = "120301")] +const MINS_PER_HOUR: u64 = 60; +#[unstable(feature = "duration_units", issue = "120301")] +const HOURS_PER_DAY: u64 = 24; +#[unstable(feature = "duration_units", issue = "120301")] +const DAYS_PER_WEEK: u64 = 7; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] @@ -286,6 +294,118 @@ impl Duration { Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32) } + /// Creates a new `Duration` from the specified number of weeks. + /// + /// # Panics + /// + /// Panics if the given number of weeks overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_weeks(4); + /// + /// assert_eq!(4 * 7 * 24 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_weeks(weeks: u64) -> Duration { + if weeks > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_WEEK) { + panic!("overflow in Duration::from_days"); + } + + Duration::from_secs(weeks * MINS_PER_HOUR * SECS_PER_MINUTE * HOURS_PER_DAY * DAYS_PER_WEEK) + } + + /// Creates a new `Duration` from the specified number of days. + /// + /// # Panics + /// + /// Panics if the given number of days overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_days(7); + /// + /// assert_eq!(7 * 24 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_days(days: u64) -> Duration { + if days > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR * HOURS_PER_DAY) { + panic!("overflow in Duration::from_days"); + } + + Duration::from_secs(days * MINS_PER_HOUR * SECS_PER_MINUTE * HOURS_PER_DAY) + } + + /// Creates a new `Duration` from the specified number of hours. + /// + /// # Panics + /// + /// Panics if the given number of hours overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_hours(6); + /// + /// assert_eq!(6 * 60 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_hours(hours: u64) -> Duration { + if hours > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR) { + panic!("overflow in Duration::from_hours"); + } + + Duration::from_secs(hours * MINS_PER_HOUR * SECS_PER_MINUTE) + } + + /// Creates a new `Duration` from the specified number of minutes. + /// + /// # Panics + /// + /// Panics if the given number of minutes overflows the `Duration` size. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let duration = Duration::from_mins(10); + /// + /// assert_eq!(10 * 60, duration.as_secs()); + /// assert_eq!(0, duration.subsec_nanos()); + /// ``` + #[unstable(feature = "duration_constructors", issue = "120301")] + #[must_use] + #[inline] + pub const fn from_mins(mins: u64) -> Duration { + if mins > u64::MAX / SECS_PER_MINUTE { + panic!("overflow in Duration::from_mins"); + } + + Duration::from_secs(mins * SECS_PER_MINUTE) + } + /// Returns true if this `Duration` spans no time. /// /// # Examples diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 89d2b5ef09383..fac83f02b26ed 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -32,6 +32,7 @@ #![feature(duration_abs_diff)] #![feature(duration_consts_float)] #![feature(duration_constants)] +#![feature(duration_constructors)] #![feature(exact_size_is_empty)] #![feature(extern_types)] #![feature(flt2dec)] diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index 23f07bf84b3db..fe7bb11c67589 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -17,6 +17,49 @@ fn new_overflow() { let _ = Duration::new(u64::MAX, 1_000_000_000); } +#[test] +#[should_panic] +fn from_mins_overflow() { + let overflow = u64::MAX / 60 + 1; + let _ = Duration::from_mins(overflow); +} + +#[test] +#[should_panic] +fn from_hours_overflow() { + let overflow = u64::MAX / (60 * 60) + 1; + let _ = Duration::from_hours(overflow); +} + +#[test] +#[should_panic] +fn from_days_overflow() { + let overflow = u64::MAX / (24 * 60 * 60) + 1; + let _ = Duration::from_days(overflow); +} + +#[test] +#[should_panic] +fn from_weeks_overflow() { + let overflow = u64::MAX / (7 * 24 * 60 * 60) + 1; + let _ = Duration::from_weeks(overflow); +} + +#[test] +fn constructors() { + assert_eq!(Duration::from_weeks(1), Duration::from_secs(7 * 24 * 60 * 60)); + assert_eq!(Duration::from_weeks(0), Duration::ZERO); + + assert_eq!(Duration::from_days(1), Duration::from_secs(86_400)); + assert_eq!(Duration::from_days(0), Duration::ZERO); + + assert_eq!(Duration::from_hours(1), Duration::from_secs(3_600)); + assert_eq!(Duration::from_hours(0), Duration::ZERO); + + assert_eq!(Duration::from_mins(1), Duration::from_secs(60)); + assert_eq!(Duration::from_mins(0), Duration::ZERO); +} + #[test] fn secs() { assert_eq!(Duration::new(0, 0).as_secs(), 0); diff --git a/src/doc/unstable-book/src/library-features/duration-constructors.md b/src/doc/unstable-book/src/library-features/duration-constructors.md new file mode 100644 index 0000000000000..098519c7c9037 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/duration-constructors.md @@ -0,0 +1,9 @@ +# `duration_constructors` + +The tracking issue for this feature is: [#120301] + +[#120301]: https://github.com/rust-lang/rust/issues/120301 + +------------------------ + +Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`.