From 3e29ffe4b21e8b1f56298703df1326529037e633 Mon Sep 17 00:00:00 2001 From: Kevin Ness Date: Fri, 19 Jul 2024 19:56:15 -0400 Subject: [PATCH] Add PartialDuration record functionality --- src/components/duration.rs | 45 ++++++++++++++++++++++++++++++++ src/components/duration/tests.rs | 14 ++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/components/duration.rs b/src/components/duration.rs index caae3694..cbb0d5e2 100644 --- a/src/components/duration.rs +++ b/src/components/duration.rs @@ -26,6 +26,31 @@ pub use date::DateDuration; #[doc(inline)] pub use time::TimeDuration; +/// A `PartialDuration` is a Duration that may have fields not set. +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] +pub struct PartialDuration { + /// A potentially existent `years` field. + pub years: Option, + /// A potentially existent `months` field. + pub months: Option, + /// A potentially existent `weeks` field. + pub weeks: Option, + /// A potentially existent `days` field. + pub days: Option, + /// A potentially existent `hours` field. + pub hours: Option, + /// A potentially existent `minutes` field. + pub minutes: Option, + /// A potentially existent `seconds` field. + pub seconds: Option, + /// A potentially existent `milliseconds` field. + pub milliseconds: Option, + /// A potentially existent `microseconds` field. + pub microseconds: Option, + /// A potentially existent `nanoseconds` field. + pub nanoseconds: Option, +} + /// The native Rust implementation of `Temporal.Duration`. /// /// `Duration` is made up of a `DateDuration` and `TimeDuration` as primarily @@ -173,6 +198,26 @@ impl Duration { } } + /// Creates a `Duration` from a provided `PartialDuration`. + pub fn from_partial_duration(partial: PartialDuration) -> TemporalResult { + if partial == PartialDuration::default() { + return Err(TemporalError::r#type() + .with_message("PartialDuration cannot have all empty fields.")); + } + Self::new( + partial.years.unwrap_or_default(), + partial.months.unwrap_or_default(), + partial.weeks.unwrap_or_default(), + partial.days.unwrap_or_default(), + partial.hours.unwrap_or_default(), + partial.minutes.unwrap_or_default(), + partial.seconds.unwrap_or_default(), + partial.milliseconds.unwrap_or_default(), + partial.microseconds.unwrap_or_default(), + partial.nanoseconds.unwrap_or_default(), + ) + } + /// Return if the Durations values are within their valid ranges. #[inline] #[must_use] diff --git a/src/components/duration/tests.rs b/src/components/duration/tests.rs index 38d200e4..6b3bdea5 100644 --- a/src/components/duration/tests.rs +++ b/src/components/duration/tests.rs @@ -658,3 +658,17 @@ fn basic_subtract_duration() { assert_eq!(result.days(), 6.0); assert_eq!(result.minutes(), 30.0); } + +#[test] +fn partial_duration_empty() { + let err = Duration::from_partial_duration(PartialDuration::default()); + assert!(err.is_err()) +} + +#[test] +fn partial_duration_values() { + let mut partial = PartialDuration::default(); + let _ = partial.years.insert(FiniteF64(20.0)); + let result = Duration::from_partial_duration(partial).unwrap(); + assert_eq!(result.years(), 20.0); +}