Skip to content

Commit ab98813

Browse files
nekevssManishearth
andauthored
Updates to PlainTime API based on review (#565)
This PR reviews the API for PlainTime. In general a variety of changes were made. - rename module from time.rs to plain_time.rs - Update the round method to use RoundingOptions over individual options. - Adds a new variant to ErrorMessage enum It's worth noting the update was also made to temporal_capi. --------- Co-authored-by: Manish Goregaokar <[email protected]>
1 parent d804513 commit ab98813

File tree

9 files changed

+88
-110
lines changed

9 files changed

+88
-110
lines changed

src/builtins/core/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod instant;
1414
mod month_day;
1515
mod plain_date;
1616
mod plain_date_time;
17-
mod time;
17+
mod plain_time;
1818
mod year_month;
1919
pub(crate) mod zoned_date_time;
2020

@@ -34,7 +34,7 @@ pub use plain_date::{PartialDate, PlainDate};
3434
#[doc(inline)]
3535
pub use plain_date_time::{DateTimeFields, PartialDateTime, PlainDateTime};
3636
#[doc(inline)]
37-
pub use time::{PartialTime, PlainTime};
37+
pub use plain_time::{PartialTime, PlainTime};
3838
#[doc(inline)]
3939
pub use year_month::{PartialYearMonth, PlainYearMonth};
4040
#[doc(inline)]

src/builtins/core/time.rs renamed to src/builtins/core/plain_time.rs

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
iso::IsoTime,
66
options::{
77
DifferenceOperation, DifferenceSettings, Overflow, ResolvedRoundingOptions,
8-
RoundingIncrement, RoundingMode, ToStringRoundingOptions, Unit, UnitGroup,
8+
RoundingOptions, ToStringRoundingOptions, Unit, UnitGroup,
99
},
1010
parsers::{parse_time, IxdtfStringBuilder},
1111
DateDuration, TemporalError, TemporalResult,
@@ -16,6 +16,8 @@ use writeable::Writeable;
1616

1717
use super::{duration::normalized::TimeDuration, PlainDateTime};
1818

19+
// TODO: add a PartialSignedTime
20+
1921
/// A `PartialTime` represents partially filled `Time` fields.
2022
#[derive(Debug, Default, Clone, Copy, PartialEq)]
2123
pub struct PartialTime {
@@ -173,13 +175,15 @@ impl PartialTime {
173175
/// ### Rounding times
174176
///
175177
/// ```rust
176-
/// use temporal_rs::{PlainTime, options::{Unit, RoundingMode}};
178+
/// use temporal_rs::{PlainTime, options::{Unit, RoundingOptions}};
177179
/// use core::str::FromStr;
178180
///
179181
/// let time = PlainTime::from_str("14:23:47.789").unwrap();
180182
///
183+
/// let mut options = RoundingOptions::default();
184+
/// options.smallest_unit = Some(Unit::Minute);
181185
/// // Round to nearest minute
182-
/// let rounded = time.round(Unit::Minute, None, None).unwrap();
186+
/// let rounded = time.round(options).unwrap();
183187
/// assert_eq!(rounded.hour(), 14);
184188
/// assert_eq!(rounded.minute(), 24);
185189
/// assert_eq!(rounded.second(), 0);
@@ -207,12 +211,6 @@ impl PlainTime {
207211
Self { iso }
208212
}
209213

210-
/// Returns true if a valid `Time`.
211-
#[allow(dead_code)]
212-
pub(crate) fn is_valid(&self) -> bool {
213-
self.iso.is_valid()
214-
}
215-
216214
/// Specification equivalent to `4.5.15 AddTime ( time, timeDuration )`
217215
///
218216
/// Spec: <https://tc39.es/proposal-temporal/#sec-temporal-addtime>
@@ -497,49 +495,26 @@ impl PlainTime {
497495
self.add_to_time(&duration.negated())
498496
}
499497

500-
#[inline]
501498
/// Returns the `Duration` until the provided `Time` from the current `Time`.
502499
///
503500
/// NOTE: `until` assumes the provided other time will occur in the future relative to the current.
501+
#[inline]
504502
pub fn until(&self, other: &Self, settings: DifferenceSettings) -> TemporalResult<Duration> {
505503
self.diff_time(DifferenceOperation::Until, other, settings)
506504
}
507505

508-
#[inline]
509506
/// Returns the `Duration` since the provided `Time` from the current `Time`.
510507
///
511508
/// NOTE: `since` assumes the provided other time is in the past relative to the current.
509+
#[inline]
512510
pub fn since(&self, other: &Self, settings: DifferenceSettings) -> TemporalResult<Duration> {
513511
self.diff_time(DifferenceOperation::Since, other, settings)
514512
}
515513

516514
// TODO (nekevss): optimize and test rounding_increment type (f64 vs. u64).
517515
/// Rounds the current `Time` according to provided options.
518-
pub fn round(
519-
&self,
520-
smallest_unit: Unit,
521-
rounding_increment: Option<f64>,
522-
rounding_mode: Option<RoundingMode>,
523-
) -> TemporalResult<Self> {
524-
let increment = RoundingIncrement::try_from(rounding_increment.unwrap_or(1.0))?;
525-
let rounding_mode = rounding_mode.unwrap_or(RoundingMode::HalfExpand);
526-
527-
let max = smallest_unit
528-
.to_maximum_rounding_increment()
529-
.ok_or_else(|| {
530-
TemporalError::range().with_message("smallestUnit must be a time value.")
531-
})?;
532-
533-
// Safety (nekevss): to_rounding_increment returns a value in the range of a u32.
534-
increment.validate(u64::from(max), false)?;
535-
536-
let resolved = ResolvedRoundingOptions {
537-
largest_unit: Unit::Auto,
538-
increment,
539-
smallest_unit,
540-
rounding_mode,
541-
};
542-
516+
pub fn round(&self, options: RoundingOptions) -> TemporalResult<Self> {
517+
let resolved = ResolvedRoundingOptions::from_time_options(options)?;
543518
let (_, result) = self.iso.round(resolved)?;
544519

545520
Ok(Self::new_unchecked(result))
@@ -565,8 +540,8 @@ impl PlainTime {
565540
}
566541

567542
impl From<PlainDateTime> for PlainTime {
568-
fn from(value: PlainDateTime) -> Self {
569-
PlainTime::new_unchecked(value.iso.time)
543+
fn from(pdt: PlainDateTime) -> Self {
544+
pdt.to_plain_time()
570545
}
571546
}
572547

@@ -587,7 +562,7 @@ mod tests {
587562
use crate::{
588563
builtins::core::Duration,
589564
iso::IsoTime,
590-
options::{DifferenceSettings, Overflow, RoundingIncrement, Unit},
565+
options::{DifferenceSettings, Overflow, RoundingIncrement, RoundingOptions, Unit},
591566
};
592567
use num_traits::FromPrimitive;
593568

@@ -630,6 +605,14 @@ mod tests {
630605
)
631606
}
632607

608+
fn options(unit: Unit, increment: f64) -> RoundingOptions {
609+
RoundingOptions {
610+
smallest_unit: Some(unit),
611+
increment: RoundingIncrement::try_from(increment).ok(),
612+
..Default::default()
613+
}
614+
}
615+
633616
#[test]
634617
fn from_str_cast_sanity_test() {
635618
let max = u32::MAX;
@@ -660,50 +643,50 @@ mod tests {
660643
fn time_round_millisecond() {
661644
let base = PlainTime::new_unchecked(IsoTime::new_unchecked(3, 34, 56, 987, 654, 321));
662645

663-
let result_1 = base.round(Unit::Millisecond, Some(1.0), None).unwrap();
646+
let result_1 = base.round(options(Unit::Millisecond, 1.0)).unwrap();
664647
assert_time(result_1, (3, 34, 56, 988, 0, 0));
665648

666-
let result_2 = base.round(Unit::Millisecond, Some(2.0), None).unwrap();
649+
let result_2 = base.round(options(Unit::Millisecond, 2.0)).unwrap();
667650
assert_time(result_2, (3, 34, 56, 988, 0, 0));
668651

669-
let result_3 = base.round(Unit::Millisecond, Some(4.0), None).unwrap();
652+
let result_3 = base.round(options(Unit::Millisecond, 4.0)).unwrap();
670653
assert_time(result_3, (3, 34, 56, 988, 0, 0));
671654

672-
let result_4 = base.round(Unit::Millisecond, Some(5.0), None).unwrap();
655+
let result_4 = base.round(options(Unit::Millisecond, 5.0)).unwrap();
673656
assert_time(result_4, (3, 34, 56, 990, 0, 0));
674657
}
675658

676659
#[test]
677660
fn time_round_microsecond() {
678661
let base = PlainTime::new_unchecked(IsoTime::new_unchecked(3, 34, 56, 987, 654, 321));
679662

680-
let result_1 = base.round(Unit::Microsecond, Some(1.0), None).unwrap();
663+
let result_1 = base.round(options(Unit::Microsecond, 1.0)).unwrap();
681664
assert_time(result_1, (3, 34, 56, 987, 654, 0));
682665

683-
let result_2 = base.round(Unit::Microsecond, Some(2.0), None).unwrap();
666+
let result_2 = base.round(options(Unit::Microsecond, 2.0)).unwrap();
684667
assert_time(result_2, (3, 34, 56, 987, 654, 0));
685668

686-
let result_3 = base.round(Unit::Microsecond, Some(4.0), None).unwrap();
669+
let result_3 = base.round(options(Unit::Microsecond, 4.0)).unwrap();
687670
assert_time(result_3, (3, 34, 56, 987, 656, 0));
688671

689-
let result_4 = base.round(Unit::Microsecond, Some(5.0), None).unwrap();
672+
let result_4 = base.round(options(Unit::Microsecond, 5.0)).unwrap();
690673
assert_time(result_4, (3, 34, 56, 987, 655, 0));
691674
}
692675

693676
#[test]
694677
fn time_round_nanoseconds() {
695678
let base = PlainTime::new_unchecked(IsoTime::new_unchecked(3, 34, 56, 987, 654, 321));
696679

697-
let result_1 = base.round(Unit::Nanosecond, Some(1.0), None).unwrap();
680+
let result_1 = base.round(options(Unit::Nanosecond, 1.0)).unwrap();
698681
assert_time(result_1, (3, 34, 56, 987, 654, 321));
699682

700-
let result_2 = base.round(Unit::Nanosecond, Some(2.0), None).unwrap();
683+
let result_2 = base.round(options(Unit::Nanosecond, 2.0)).unwrap();
701684
assert_time(result_2, (3, 34, 56, 987, 654, 322));
702685

703-
let result_3 = base.round(Unit::Nanosecond, Some(4.0), None).unwrap();
686+
let result_3 = base.round(options(Unit::Nanosecond, 4.0)).unwrap();
704687
assert_time(result_3, (3, 34, 56, 987, 654, 320));
705688

706-
let result_4 = base.round(Unit::Nanosecond, Some(5.0), None).unwrap();
689+
let result_4 = base.round(options(Unit::Nanosecond, 5.0)).unwrap();
707690
assert_time(result_4, (3, 34, 56, 987, 654, 320));
708691
}
709692

@@ -796,63 +779,63 @@ mod tests {
796779
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 321, Overflow::Constrain).unwrap();
797780

798781
assert_eq!(
799-
time.round(Unit::Nanosecond, Some(1.0), None).unwrap(),
782+
time.round(options(Unit::Nanosecond, 1.0)).unwrap(),
800783
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 321, Overflow::Constrain).unwrap()
801784
);
802785
assert_eq!(
803-
time.round(Unit::Nanosecond, Some(2.0), None).unwrap(),
786+
time.round(options(Unit::Nanosecond, 2.0)).unwrap(),
804787
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 322, Overflow::Constrain).unwrap()
805788
);
806789
assert_eq!(
807-
time.round(Unit::Nanosecond, Some(4.0), None).unwrap(),
790+
time.round(options(Unit::Nanosecond, 4.0)).unwrap(),
808791
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
809792
);
810793
assert_eq!(
811-
time.round(Unit::Nanosecond, Some(5.0), None).unwrap(),
794+
time.round(options(Unit::Nanosecond, 5.0)).unwrap(),
812795
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
813796
);
814797
assert_eq!(
815-
time.round(Unit::Nanosecond, Some(8.0), None).unwrap(),
798+
time.round(options(Unit::Nanosecond, 8.0)).unwrap(),
816799
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
817800
);
818801
assert_eq!(
819-
time.round(Unit::Nanosecond, Some(10.0), None).unwrap(),
802+
time.round(options(Unit::Nanosecond, 10.0)).unwrap(),
820803
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
821804
);
822805
assert_eq!(
823-
time.round(Unit::Nanosecond, Some(20.0), None).unwrap(),
806+
time.round(options(Unit::Nanosecond, 20.0)).unwrap(),
824807
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
825808
);
826809
assert_eq!(
827-
time.round(Unit::Nanosecond, Some(25.0), None).unwrap(),
810+
time.round(options(Unit::Nanosecond, 25.0)).unwrap(),
828811
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 325, Overflow::Constrain).unwrap()
829812
);
830813
assert_eq!(
831-
time.round(Unit::Nanosecond, Some(40.0), None).unwrap(),
814+
time.round(options(Unit::Nanosecond, 40.0)).unwrap(),
832815
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 320, Overflow::Constrain).unwrap()
833816
);
834817
assert_eq!(
835-
time.round(Unit::Nanosecond, Some(50.0), None).unwrap(),
818+
time.round(options(Unit::Nanosecond, 50.0)).unwrap(),
836819
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 300, Overflow::Constrain).unwrap()
837820
);
838821
assert_eq!(
839-
time.round(Unit::Nanosecond, Some(100.0), None).unwrap(),
822+
time.round(options(Unit::Nanosecond, 100.0)).unwrap(),
840823
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 300, Overflow::Constrain).unwrap()
841824
);
842825
assert_eq!(
843-
time.round(Unit::Nanosecond, Some(125.0), None).unwrap(),
826+
time.round(options(Unit::Nanosecond, 125.0)).unwrap(),
844827
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 375, Overflow::Constrain).unwrap()
845828
);
846829
assert_eq!(
847-
time.round(Unit::Nanosecond, Some(200.0), None).unwrap(),
830+
time.round(options(Unit::Nanosecond, 200.0)).unwrap(),
848831
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 400, Overflow::Constrain).unwrap()
849832
);
850833
assert_eq!(
851-
time.round(Unit::Nanosecond, Some(250.0), None).unwrap(),
834+
time.round(options(Unit::Nanosecond, 250.0)).unwrap(),
852835
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 250, Overflow::Constrain).unwrap()
853836
);
854837
assert_eq!(
855-
time.round(Unit::Nanosecond, Some(500.0), None).unwrap(),
838+
time.round(options(Unit::Nanosecond, 500.0)).unwrap(),
856839
PlainTime::new_with_overflow(3, 34, 56, 987, 654, 500, Overflow::Constrain).unwrap()
857840
);
858841
}

src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ pub(crate) enum ErrorMessage {
177177
FractionalDigitsPrecisionInvalid,
178178

179179
// Options validity
180+
SmallestUnitIsRequired,
180181
SmallestUnitNotTimeUnit,
181182
SmallestUnitLargerThanLargestUnit,
182183
UnitNotDate,
@@ -222,6 +223,7 @@ impl ErrorMessage {
222223
Self::NumberNotPositive => "integer must be positive.",
223224
Self::NumberOutOfRange => "number exceeded a valid range.",
224225
Self::FractionalDigitsPrecisionInvalid => "Invalid fractionalDigits precision value",
226+
Self::SmallestUnitIsRequired => "smallestUnit is required",
225227
Self::SmallestUnitNotTimeUnit => "smallestUnit must be a valid time unit.",
226228
Self::SmallestUnitLargerThanLargestUnit => {
227229
"smallestUnit was larger than largestunit in DifferenceeSettings"

src/iso.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -845,23 +845,6 @@ impl IsoTime {
845845
}
846846
}
847847

848-
/// Checks if the time is a valid `IsoTime`
849-
pub(crate) fn is_valid(&self) -> bool {
850-
if !(0..=23).contains(&self.hour) {
851-
return false;
852-
}
853-
854-
let min_sec = 0..=59;
855-
if !min_sec.contains(&self.minute) || !min_sec.contains(&self.second) {
856-
return false;
857-
}
858-
859-
let sub_second = 0..=999;
860-
sub_second.contains(&self.millisecond)
861-
&& sub_second.contains(&self.microsecond)
862-
&& sub_second.contains(&self.nanosecond)
863-
}
864-
865848
pub(crate) fn add(&self, norm: TimeDuration) -> (i64, Self) {
866849
// 1. Set second to second + TimeDurationSeconds(norm).
867850
let seconds = i64::from(self.second) + norm.seconds();

src/options.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,30 @@ impl ResolvedRoundingOptions {
258258
})
259259
}
260260

261+
pub(crate) fn from_time_options(options: RoundingOptions) -> TemporalResult<Self> {
262+
let Some(smallest_unit) = options.smallest_unit else {
263+
return Err(TemporalError::range().with_enum(ErrorMessage::SmallestUnitIsRequired));
264+
};
265+
let increment = options.increment.unwrap_or(RoundingIncrement::ONE);
266+
let rounding_mode = options.rounding_mode.unwrap_or(RoundingMode::HalfExpand);
267+
268+
let max = smallest_unit
269+
.to_maximum_rounding_increment()
270+
.ok_or_else(|| {
271+
TemporalError::range().with_enum(ErrorMessage::SmallestUnitNotTimeUnit)
272+
})?;
273+
274+
// Safety (nekevss): to_rounding_increment returns a value in the range of a u32.
275+
increment.validate(u64::from(max), false)?;
276+
277+
Ok(ResolvedRoundingOptions {
278+
largest_unit: Unit::Auto,
279+
increment,
280+
smallest_unit,
281+
rounding_mode,
282+
})
283+
}
284+
261285
pub(crate) fn from_instant_options(options: RoundingOptions) -> TemporalResult<Self> {
262286
let increment = options.increment.unwrap_or_default();
263287
let rounding_mode = options.rounding_mode.unwrap_or_default();

temporal_capi/bindings/c/PlainTime.h

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)