Skip to content

Commit b44fb0e

Browse files
committed
Update IncrementRounder to use NonZeroU64
1 parent 207db41 commit b44fb0e

File tree

10 files changed

+178
-88
lines changed

10 files changed

+178
-88
lines changed

src/components/duration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ impl Duration {
614614
} else {
615615
// NOTE: DateDuration::round will always return a NormalizedTime::default as per spec.
616616
// a. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundResult.[[NormalizedTime]], roundResult.[[Days]]).
617-
let norm_with_days = round_result.0 .1.add_days(round_result.0 .0.days)?;
617+
let norm_with_days = round_result.0 .1.add_days(round_result.0 .0.days as i64)?;
618618
// b. Let balanceResult be BalanceTimeDuration(normWithDays, largestUnit).
619619
TimeDuration::from_normalized(norm_with_days, largest_unit)?
620620
};

src/components/duration/date.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,6 @@ impl DateDuration {
448448
_precalculated_dt: Option<DateTime<C>>,
449449
context: &mut C::Context,
450450
) -> TemporalResult<(Self, f64)> {
451-
let increment = f64::from(increment.0.get());
452-
453451
// 1. If plainRelativeTo is not present, set plainRelativeTo to undefined.
454452
let plain_relative_to = relative_to.date;
455453
// 2. If zonedRelativeTo is not present, set zonedRelativeTo to undefined.
@@ -581,9 +579,11 @@ impl DateDuration {
581579
let frac_years = years + (fractional_days / one_year_days.abs());
582580

583581
// ab. Set years to RoundNumberToIncrement(fractionalYears, increment, roundingMode).
584-
let rounded_years =
585-
IncrementRounder::<f64>::from_potentially_negative_parts(frac_years, increment)
586-
.round(rounding_mode);
582+
let rounded_years = IncrementRounder::<f64>::from_potentially_negative_parts(
583+
frac_years,
584+
increment.as_extended_increment(),
585+
)?
586+
.round(rounding_mode);
587587

588588
// ac. Set total to fractionalYears.
589589
// ad. Set months and weeks to 0.
@@ -666,8 +666,8 @@ impl DateDuration {
666666
// r. Set months to RoundNumberToIncrement(fractionalMonths, increment, roundingMode).
667667
let rounded_months = IncrementRounder::<f64>::from_potentially_negative_parts(
668668
frac_months,
669-
increment,
670-
)
669+
increment.as_extended_increment(),
670+
)?
671671
.round(rounding_mode);
672672

673673
// s. Set total to fractionalMonths.
@@ -719,9 +719,11 @@ impl DateDuration {
719719
let frac_weeks = weeks + fractional_days / one_week_days.abs();
720720

721721
// k. Set weeks to RoundNumberToIncrement(fractionalWeeks, increment, roundingMode).
722-
let rounded_weeks =
723-
IncrementRounder::<f64>::from_potentially_negative_parts(frac_weeks, increment)
724-
.round(rounding_mode);
722+
let rounded_weeks = IncrementRounder::<f64>::from_potentially_negative_parts(
723+
frac_weeks,
724+
increment.as_extended_increment(),
725+
)?
726+
.round(rounding_mode);
725727
// l. Set total to fractionalWeeks.
726728
let result = Self::new(self.years, self.months, rounded_weeks as f64, 0f64)?;
727729
Ok((result, frac_weeks))
@@ -731,8 +733,8 @@ impl DateDuration {
731733
// a. Set days to RoundNumberToIncrement(fractionalDays, increment, roundingMode).
732734
let rounded_days = IncrementRounder::<f64>::from_potentially_negative_parts(
733735
fractional_days,
734-
increment,
735-
)
736+
increment.as_extended_increment(),
737+
)?
736738
.round(rounding_mode);
737739

738740
// b. Set total to fractionalDays.

src/components/duration/normalized.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This module implements the normalized `Duration` records.
22
3-
use std::ops::Add;
3+
use std::{num::NonZeroU64, ops::Add};
44

55
use num_traits::Euclid;
66

@@ -40,11 +40,11 @@ impl NormalizedTimeDuration {
4040
Self(nanoseconds)
4141
}
4242

43-
// NOTE: `days: f64` should be an integer.
43+
// NOTE: `days: f64` should be an integer -> `i64`.
4444
/// Equivalent: 7.5.23 Add24HourDaysToNormalizedTimeDuration ( d, days )
4545
#[allow(unused)]
46-
pub(super) fn add_days(&self, days: f64) -> TemporalResult<Self> {
47-
let result = self.0 + i128::from(days as i64 * NS_PER_DAY);
46+
pub(super) fn add_days(&self, days: i64) -> TemporalResult<Self> {
47+
let result = self.0 + i128::from(days * NS_PER_DAY as i64);
4848
if result.abs() > MAX_TIME_DURATION {
4949
return Err(TemporalError::range()
5050
.with_message("normalizedTimeDuration exceeds maxTimeDuration."));
@@ -88,10 +88,13 @@ impl NormalizedTimeDuration {
8888
}
8989

9090
/// Round the current `NormalizedTimeDuration`.
91-
pub(super) fn round(&self, increment: u64, mode: TemporalRoundingMode) -> TemporalResult<Self> {
92-
let rounded =
93-
IncrementRounder::<i128>::from_potentially_negative_parts(self.0, increment.into())
94-
.round(mode);
91+
pub(super) fn round(
92+
&self,
93+
increment: NonZeroU64,
94+
mode: TemporalRoundingMode,
95+
) -> TemporalResult<Self> {
96+
let rounded = IncrementRounder::<i128>::from_potentially_negative_parts(self.0, increment)?
97+
.round(mode);
9598
if rounded.abs() > MAX_TIME_DURATION {
9699
return Err(TemporalError::range()
97100
.with_message("normalizedTimeDuration exceeds maxTimeDuration."));

src/components/duration/time.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! An implementation of `TimeDuration` and it's methods.
22
3+
use std::num::NonZeroU64;
4+
35
use crate::{
46
options::{RoundingIncrement, TemporalRoundingMode, TemporalUnit},
5-
TemporalError, TemporalResult,
7+
TemporalError, TemporalResult, TemporalUnwrap,
68
};
79

810
use super::{is_valid_duration, normalized::NormalizedTimeDuration};
@@ -373,7 +375,6 @@ impl TimeDuration {
373375
unit: TemporalUnit,
374376
mode: TemporalRoundingMode,
375377
) -> TemporalResult<(NormalizedTimeDuration, i64)> {
376-
let increment = u64::from(increment.0.get());
377378
let norm = match unit {
378379
TemporalUnit::Year
379380
| TemporalUnit::Month
@@ -393,7 +394,11 @@ impl TimeDuration {
393394
// b. Set total to DivideNormalizedTimeDuration(norm, divisor).
394395
let total = norm.divide(NANOSECONDS_PER_HOUR as i64);
395396
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
396-
let norm = norm.round(NANOSECONDS_PER_HOUR * increment, mode)?;
397+
let increment_mul_divisor = increment
398+
.as_extended_increment()
399+
.checked_mul(unsafe { NonZeroU64::new_unchecked(NANOSECONDS_PER_HOUR) })
400+
.temporal_unwrap()?;
401+
let norm = norm.round(increment_mul_divisor, mode)?;
397402
Ok((norm, total as i64))
398403
}
399404
// 13. Else if unit is "minute", then
@@ -402,7 +407,11 @@ impl TimeDuration {
402407
// b. Set total to DivideNormalizedTimeDuration(norm, divisor).
403408
let total = norm.divide(NANOSECONDS_PER_MINUTE as i64);
404409
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
405-
let norm = norm.round(NANOSECONDS_PER_MINUTE * increment, mode)?;
410+
let increment_mul_divisor = increment
411+
.as_extended_increment()
412+
.checked_mul(unsafe { NonZeroU64::new_unchecked(NANOSECONDS_PER_MINUTE) })
413+
.temporal_unwrap()?;
414+
let norm = norm.round(increment_mul_divisor, mode)?;
406415
Ok((norm, total as i64))
407416
}
408417
// 14. Else if unit is "second", then
@@ -411,7 +420,11 @@ impl TimeDuration {
411420
// b. Set total to DivideNormalizedTimeDuration(norm, divisor).
412421
let total = norm.divide(NANOSECONDS_PER_SECOND as i64);
413422
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
414-
let norm = norm.round(NANOSECONDS_PER_SECOND * increment, mode)?;
423+
let increment_mul_divisor = increment
424+
.as_extended_increment()
425+
.checked_mul(unsafe { NonZeroU64::new_unchecked(NANOSECONDS_PER_SECOND) })
426+
.temporal_unwrap()?;
427+
let norm = norm.round(increment_mul_divisor, mode)?;
415428
Ok((norm, total as i64))
416429
}
417430
// 15. Else if unit is "millisecond", then
@@ -420,7 +433,11 @@ impl TimeDuration {
420433
// b. Set total to DivideNormalizedTimeDuration(norm, divisor).
421434
let total = norm.divide(1_000_000);
422435
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
423-
let norm = norm.round(1_000_000 * increment, mode)?;
436+
let increment_mul_divisor = increment
437+
.as_extended_increment()
438+
.checked_mul(unsafe { NonZeroU64::new_unchecked(1_000_000) })
439+
.temporal_unwrap()?;
440+
let norm = norm.round(increment_mul_divisor, mode)?;
424441
Ok((norm, total as i64))
425442
}
426443
// 16. Else if unit is "microsecond", then
@@ -429,7 +446,11 @@ impl TimeDuration {
429446
// b. Set total to DivideNormalizedTimeDuration(norm, divisor).
430447
let total = norm.divide(1_000);
431448
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
432-
let norm = norm.round(1_000 * increment, mode)?;
449+
let increment_mul_divisor = increment
450+
.as_extended_increment()
451+
.checked_mul(unsafe { NonZeroU64::new_unchecked(1_000) })
452+
.temporal_unwrap()?;
453+
let norm = norm.round(increment_mul_divisor, mode)?;
433454
Ok((norm, total as i64))
434455
}
435456
// 17. Else,
@@ -439,7 +460,7 @@ impl TimeDuration {
439460
let total =
440461
norm.seconds() * (NANOSECONDS_PER_SECOND as i64) + i64::from(norm.subseconds());
441462
// c. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, increment, roundingMode).
442-
let norm = norm.round(increment, mode)?;
463+
let norm = norm.round(increment.as_extended_increment(), mode)?;
443464
Ok((norm, total))
444465
}
445466
_ => unreachable!("All other units early return error."),

src/components/instant.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! An implementation of the Temporal Instant.
22
3+
use std::num::NonZeroU64;
4+
35
use crate::{
46
components::{duration::TimeDuration, Duration},
57
options::{RoundingIncrement, TemporalRoundingMode, TemporalUnit},
68
rounding::{IncrementRounder, Round},
7-
TemporalError, TemporalResult, MS_PER_DAY, NS_PER_DAY,
9+
TemporalError, TemporalResult, TemporalUnwrap, MS_PER_DAY, NS_PER_DAY,
810
};
911

1012
use num_bigint::BigInt;
@@ -103,21 +105,33 @@ impl Instant {
103105
unit: TemporalUnit,
104106
rounding_mode: TemporalRoundingMode,
105107
) -> TemporalResult<BigInt> {
106-
let increment = u64::from(increment.0.get());
108+
let increment = increment.as_extended_increment();
107109
let increment = match unit {
108-
TemporalUnit::Hour => increment * (NANOSECONDS_PER_HOUR as u64),
109-
TemporalUnit::Minute => increment * (NANOSECONDS_PER_MINUTE as u64),
110-
TemporalUnit::Second => increment * (NANOSECONDS_PER_SECOND as u64),
111-
TemporalUnit::Millisecond => increment * 1_000_000,
112-
TemporalUnit::Microsecond => increment * 1_000,
113-
TemporalUnit::Nanosecond => increment,
110+
TemporalUnit::Hour => increment
111+
.checked_mul(NonZeroU64::new(NANOSECONDS_PER_HOUR as u64).temporal_unwrap()?),
112+
TemporalUnit::Minute => increment
113+
.checked_mul(NonZeroU64::new(NANOSECONDS_PER_MINUTE as u64).temporal_unwrap()?),
114+
TemporalUnit::Second => increment
115+
.checked_mul(NonZeroU64::new(NANOSECONDS_PER_SECOND as u64).temporal_unwrap()?),
116+
TemporalUnit::Millisecond => {
117+
increment.checked_mul(NonZeroU64::new(1_000_000).temporal_unwrap()?)
118+
}
119+
TemporalUnit::Microsecond => {
120+
increment.checked_mul(NonZeroU64::new(1_000).temporal_unwrap()?)
121+
}
122+
TemporalUnit::Nanosecond => Some(increment),
114123
_ => {
115124
return Err(TemporalError::range()
116125
.with_message("Invalid unit provided for Instant::round."))
117126
}
118127
};
119128

120-
let rounded = IncrementRounder::<f64>::from_positive_parts(self.to_f64(), increment as f64)
129+
// NOTE: Potentially remove the below and just `temporal_unwrap`
130+
let Some(increment) = increment else {
131+
return Err(TemporalError::range().with_message("Increment exceeded a valid range."));
132+
};
133+
134+
let rounded = IncrementRounder::<f64>::from_positive_parts(self.to_f64(), increment)?
121135
.round_as_positive(rounding_mode);
122136

123137
BigInt::from_u64(rounded)
@@ -238,7 +252,7 @@ impl Instant {
238252
TemporalUnit::Second => 24 * 3600,
239253
TemporalUnit::Millisecond => MS_PER_DAY as u64,
240254
TemporalUnit::Microsecond => MS_PER_DAY as u64 * 1000,
241-
TemporalUnit::Nanosecond => NS_PER_DAY as u64,
255+
TemporalUnit::Nanosecond => NS_PER_DAY,
242256
_ => return Err(TemporalError::range().with_message("Invalid roundTo unit provided.")),
243257
};
244258
// NOTE: to_rounding_increment returns an f64 within a u32 range.

src/iso.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
//!
1313
//! An `IsoDateTime` has the internal slots of both an `IsoDate` and `IsoTime`.
1414
15+
use std::num::NonZeroU64;
16+
1517
use crate::{
1618
components::{
1719
calendar::{CalendarProtocol, CalendarSlot},
@@ -21,7 +23,7 @@ use crate::{
2123
error::TemporalError,
2224
options::{ArithmeticOverflow, RoundingIncrement, TemporalRoundingMode, TemporalUnit},
2325
rounding::{IncrementRounder, Round},
24-
utils, TemporalResult, NS_PER_DAY,
26+
utils, TemporalResult, TemporalUnwrap, NS_PER_DAY,
2527
};
2628
use icu_calendar::{Date as IcuDate, Iso};
2729
use num_bigint::BigInt;
@@ -554,7 +556,7 @@ impl IsoTime {
554556
increment: RoundingIncrement,
555557
unit: TemporalUnit,
556558
mode: TemporalRoundingMode,
557-
day_length_ns: Option<i64>,
559+
day_length_ns: Option<u64>,
558560
) -> TemporalResult<(i32, Self)> {
559561
// 1. Let fractionalSecond be nanosecond × 10-9 + microsecond × 10-6 + millisecond × 10-3 + second.
560562

@@ -612,19 +614,22 @@ impl IsoTime {
612614
};
613615

614616
let ns_per_unit = if unit == TemporalUnit::Day {
615-
day_length_ns.unwrap_or(NS_PER_DAY)
617+
unsafe { NonZeroU64::new_unchecked(day_length_ns.unwrap_or(NS_PER_DAY)) }
616618
} else {
617-
unit.as_nanoseconds().expect("Only valid time values are ") as i64
619+
let nanos = unit.as_nanoseconds().temporal_unwrap()?;
620+
unsafe { NonZeroU64::new_unchecked(nanos) }
618621
};
619622

623+
let increment = ns_per_unit
624+
.checked_mul(increment.as_extended_increment())
625+
.temporal_unwrap()?;
626+
620627
// TODO: Verify validity of cast or handle better for result.
621628
// 9. Let result be RoundNumberToIncrement(quantity, increment, roundingMode).
622-
let result = IncrementRounder::<i128>::from_potentially_negative_parts(
623-
quantity.into(),
624-
ns_per_unit as i128 * u64::from(increment.get()) as i128,
625-
)
626-
.round(mode)
627-
/ ns_per_unit as i128;
629+
let result =
630+
IncrementRounder::<i128>::from_potentially_negative_parts(quantity.into(), increment)?
631+
.round(mode)
632+
/ i128::from(ns_per_unit.get());
628633

629634
let result = match unit {
630635
// 10. If unit is "day", then

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ impl<T> TemporalUnwrap for Option<T> {
8282

8383
// Relevant numeric constants
8484
/// Nanoseconds per day constant: 8.64e+13
85-
pub const NS_PER_DAY: i64 = MS_PER_DAY as i64 * 1_000_000;
85+
pub const NS_PER_DAY: u64 = MS_PER_DAY as u64 * 1_000_000;
8686
/// Milliseconds per day constant: 8.64e+7
87-
pub const MS_PER_DAY: i32 = 24 * 60 * 60 * 1000;
87+
pub const MS_PER_DAY: u32 = 24 * 60 * 60 * 1000;
8888
/// Max Instant nanosecond constant
8989
#[doc(hidden)]
9090
pub(crate) const NS_MAX_INSTANT: i128 = NS_PER_DAY as i128 * 100_000_000i128;

src/options.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ impl TemporalUnit {
8181
// TODO: potentiall use a u64
8282
/// Returns the `Nanosecond amount for any given value.`
8383
#[must_use]
84-
pub fn as_nanoseconds(&self) -> Option<f64> {
84+
pub fn as_nanoseconds(&self) -> Option<u64> {
8585
use TemporalUnit::{
8686
Auto, Day, Hour, Microsecond, Millisecond, Minute, Month, Nanosecond, Second, Week,
8787
Year,
8888
};
8989
match self {
9090
Year | Month | Week | Day | Auto => None,
91-
Hour => Some(3600e9),
92-
Minute => Some(60e9),
93-
Second => Some(1e9),
94-
Millisecond => Some(1e6),
95-
Microsecond => Some(1e3),
96-
Nanosecond => Some(1f64),
91+
Hour => Some(3_600_000_000_000),
92+
Minute => Some(60_000_000_000),
93+
Second => Some(1_000_000_000),
94+
Millisecond => Some(1_000_000),
95+
Microsecond => Some(1_000),
96+
Nanosecond => Some(1),
9797
}
9898
}
9999

src/options/increment.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::num::NonZeroU32;
1+
use std::num::{NonZeroU32, NonZeroU64};
22

33
use crate::{TemporalError, TemporalResult};
44

@@ -106,4 +106,8 @@ impl RoundingIncrement {
106106
// 5. Return unused.
107107
Ok(())
108108
}
109+
110+
pub(crate) fn as_extended_increment(&self) -> NonZeroU64 {
111+
NonZeroU64::from(self.0)
112+
}
109113
}

0 commit comments

Comments
 (0)