diff --git a/src/duration.rs b/src/duration.rs index f00b03663e..098169627e 100644 --- a/src/duration.rs +++ b/src/duration.rs @@ -19,24 +19,10 @@ use std::error::Error; #[cfg(feature = "rkyv")] use rkyv::{Archive, Deserialize, Serialize}; -/// The number of nanoseconds in a microsecond. -const NANOS_PER_MICRO: i32 = 1000; -/// The number of nanoseconds in a millisecond. -const NANOS_PER_MILLI: i32 = 1_000_000; -/// The number of nanoseconds in seconds. -const NANOS_PER_SEC: i32 = 1_000_000_000; -/// The number of microseconds per second. -const MICROS_PER_SEC: i64 = 1_000_000; -/// The number of milliseconds per second. -const MILLIS_PER_SEC: i64 = 1000; -/// The number of seconds in a minute. -const SECS_PER_MINUTE: i64 = 60; -/// The number of seconds in an hour. -const SECS_PER_HOUR: i64 = 3600; -/// The number of (non-leap) seconds in days. -const SECS_PER_DAY: i64 = 86_400; -/// The number of (non-leap) seconds in a week. -const SECS_PER_WEEK: i64 = 604_800; +use crate::{ + MICROS_PER_SEC, MILLIS_PER_SEC, NANOS_PER_MICRO, NANOS_PER_MILLI, NANOS_PER_SEC, SECS_PER_DAY, + SECS_PER_HOUR, SECS_PER_MINUTE, SECS_PER_WEEK, +}; macro_rules! try_opt { ($e:expr) => { @@ -221,7 +207,9 @@ impl Duration { } } - /// Returns the number of nanoseconds such that + /// Returns the number of nanoseconds in the fractional part of the duration. + /// + /// This is the number of nanoseconds such that /// `subsec_nanos() + num_seconds() * NANOS_PER_SEC` is the total number of /// nanoseconds in the duration. pub const fn subsec_nanos(&self) -> i32 { @@ -232,6 +220,24 @@ impl Duration { } } + /// Returns the number of microseconds in the fractional part of the duration. + /// + /// This is the number of microseconds such that + /// `subsec_micros() + num_seconds() * MICROS_PER_SEC` is the total number of + /// microseconds in the duration. + pub const fn subsec_micros(&self) -> i32 { + self.subsec_nanos() / NANOS_PER_MICRO + } + + /// Returns the number of milliseconds in the fractional part of the duration. + /// + /// This is the number of milliseconds such that + /// `subsec_millis() + num_seconds() * MILLIS_PER_SEC` is the total number of + /// milliseconds in the duration. + pub const fn subsec_millis(&self) -> i32 { + self.subsec_nanos() / NANOS_PER_MILLI + } + /// Returns the total number of whole milliseconds in the duration, pub const fn num_milliseconds(&self) -> i64 { // A proper Duration will not overflow, because MIN and MAX are defined @@ -647,6 +653,33 @@ mod tests { assert_eq!(Duration::days(-i64::MAX / NANOS_PER_DAY - 1).num_nanoseconds(), None); } + #[test] + fn test_duration_subsec_nanos() { + assert_eq!(Duration::zero().subsec_nanos(), 0); + assert_eq!(Duration::nanoseconds(1).subsec_nanos(), 1); + assert_eq!(Duration::nanoseconds(-1).subsec_nanos(), -1); + assert_eq!(Duration::seconds(1).subsec_nanos(), 0); + assert_eq!(Duration::nanoseconds(1_000_000_001).subsec_nanos(), 1); + } + + #[test] + fn test_duration_subsec_micros() { + assert_eq!(Duration::zero().subsec_micros(), 0); + assert_eq!(Duration::microseconds(1).subsec_micros(), 1); + assert_eq!(Duration::microseconds(-1).subsec_micros(), -1); + assert_eq!(Duration::seconds(1).subsec_micros(), 0); + assert_eq!(Duration::microseconds(1_000_001).subsec_micros(), 1); + } + + #[test] + fn test_duration_subsec_millis() { + assert_eq!(Duration::zero().subsec_millis(), 0); + assert_eq!(Duration::milliseconds(1).subsec_millis(), 1); + assert_eq!(Duration::milliseconds(-1).subsec_millis(), -1); + assert_eq!(Duration::seconds(1).subsec_millis(), 0); + assert_eq!(Duration::milliseconds(1_000_001).subsec_millis(), 1); + } + #[test] fn test_duration_checked_ops() { assert_eq!( diff --git a/src/lib.rs b/src/lib.rs index da8e00d17a..ef410f5408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -585,6 +585,25 @@ pub mod rkyv { pub use crate::weekday::ArchivedWeekday; } +/// The number of nanoseconds in a microsecond. +pub const NANOS_PER_MICRO: i32 = 1000; +/// The number of nanoseconds in a millisecond. +pub const NANOS_PER_MILLI: i32 = 1_000_000; +/// The number of nanoseconds in a second. +pub const NANOS_PER_SEC: i32 = 1_000_000_000; +/// The number of microseconds in a second. +pub const MICROS_PER_SEC: i64 = 1_000_000; +/// The number of milliseconds in a second. +pub const MILLIS_PER_SEC: i64 = 1000; +/// The number of seconds in a minute. +pub const SECS_PER_MINUTE: i64 = 60; +/// The number of seconds in an hour. +pub const SECS_PER_HOUR: i64 = 3600; +/// The number of (non-leap) seconds in a day. +pub const SECS_PER_DAY: i64 = 86_400; +/// The number of (non-leap) seconds in a week. +pub const SECS_PER_WEEK: i64 = 604_800; + /// Out of range error type used in various converting APIs #[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct OutOfRange {