Skip to content

Commit e34d24b

Browse files
committed
Remove previous round implementation and adjust fix tests
1 parent cb6c41a commit e34d24b

File tree

9 files changed

+109
-684
lines changed

9 files changed

+109
-684
lines changed

src/components/duration.rs

Lines changed: 5 additions & 251 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
use ixdtf::parsers::{records::TimeDurationRecord, IsoDurationParser};
1010
use std::str::FromStr;
1111

12-
use self::normalized::{NormalizedDurationRecord, NormalizedTimeDuration};
12+
use self::normalized::NormalizedTimeDuration;
1313

1414
mod date;
1515
pub(crate) mod normalized;
@@ -357,58 +357,6 @@ impl Duration {
357357
}
358358
}
359359

360-
// ==== Private Duration methods ====
361-
362-
impl Duration {
363-
// TODO (nekevss): Build out `RelativeTo` handling
364-
/// Abstract Operation 7.5.26 `RoundDuration ( years, months, weeks, days, hours, minutes,
365-
/// seconds, milliseconds, microseconds, nanoseconds, increment, unit,
366-
/// roundingMode [ , plainRelativeTo [, zonedRelativeTo [, precalculatedDateTime]]] )`
367-
#[allow(clippy::type_complexity)]
368-
pub(crate) fn round_internal(
369-
&self,
370-
increment: RoundingIncrement,
371-
unit: TemporalUnit,
372-
rounding_mode: TemporalRoundingMode,
373-
relative_to: &RelativeTo,
374-
precalculated_dt: Option<DateTime>,
375-
) -> TemporalResult<(NormalizedDurationRecord, f64)> {
376-
match unit {
377-
TemporalUnit::Year | TemporalUnit::Month | TemporalUnit::Week | TemporalUnit::Day => {
378-
let round_result = self.date().round(
379-
Some(self.time.to_normalized()),
380-
increment,
381-
unit,
382-
rounding_mode,
383-
relative_to,
384-
precalculated_dt,
385-
)?;
386-
let norm_record = NormalizedDurationRecord::new(
387-
round_result.0,
388-
NormalizedTimeDuration::default(),
389-
)?;
390-
Ok((norm_record, round_result.1))
391-
}
392-
TemporalUnit::Hour
393-
| TemporalUnit::Minute
394-
| TemporalUnit::Second
395-
| TemporalUnit::Millisecond
396-
| TemporalUnit::Microsecond
397-
| TemporalUnit::Nanosecond => {
398-
let round_result = self.time().round(increment, unit, rounding_mode)?;
399-
let norm = NormalizedDurationRecord::new(*self.date(), round_result.0)?;
400-
Ok((norm, round_result.1 as f64))
401-
}
402-
TemporalUnit::Auto => {
403-
Err(TemporalError::range().with_message("Invalid TemporalUnit for Duration.round"))
404-
}
405-
}
406-
// 18. Let duration be ? CreateDurationRecord(years, months, weeks, days, hours,
407-
// minutes, seconds, milliseconds, microseconds, nanoseconds).
408-
// 19. Return the Record { [[DurationRecord]]: duration, [[Total]]: total }.
409-
}
410-
}
411-
412360
// ==== Public Duration methods ====
413361

414362
impl Duration {
@@ -449,7 +397,7 @@ impl Duration {
449397
}
450398

451399
#[inline]
452-
pub fn round_v2(
400+
pub fn round(
453401
&self,
454402
increment: Option<RoundingIncrement>,
455403
smallest_unit: Option<TemporalUnit>,
@@ -647,7 +595,9 @@ impl Duration {
647595
)?;
648596
// d. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundRecord.[[NormalizedDuration]].[[NormalizedTime]],
649597
// roundRecord.[[NormalizedDuration]].[[Days]]).
650-
let norm_with_days = round_record.0 .1.add_days(round_record.0 .0.days as i64)?;
598+
let norm_with_days = round_record
599+
.norm()
600+
.add_days(round_record.date().days as i64)?;
651601
// e. Let balanceResult be ? BalanceTimeDuration(normWithDays, largestUnit).
652602
let (balanced_days, balanced_time) =
653603
TimeDuration::from_normalized(norm_with_days, largest_unit)?;
@@ -660,202 +610,6 @@ impl Duration {
660610
// 41. Return ? CreateTemporalDuration(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]]).
661611
Ok(round_result)
662612
}
663-
664-
/// Rounds the current `Duration`.
665-
#[inline]
666-
pub fn round(
667-
&self,
668-
increment: Option<RoundingIncrement>,
669-
smallest_unit: Option<TemporalUnit>,
670-
largest_unit: Option<TemporalUnit>,
671-
rounding_mode: Option<TemporalRoundingMode>,
672-
relative_to: &RelativeTo,
673-
) -> TemporalResult<Self> {
674-
// NOTE: Steps 1-14 seem to be implementation specific steps.
675-
676-
// 22. If smallestUnitPresent is false and largestUnitPresent is false, then
677-
if largest_unit.is_none() && smallest_unit.is_none() {
678-
// a. Throw a RangeError exception.
679-
return Err(TemporalError::range()
680-
.with_message("smallestUnit and largestUnit cannot both be None."));
681-
}
682-
683-
// 14. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
684-
let increment = increment.unwrap_or_default();
685-
// 15. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
686-
let mode = rounding_mode.unwrap_or_default();
687-
688-
// 16. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", DATETIME, undefined).
689-
// 17. If smallestUnit is undefined, then
690-
// a. Set smallestUnitPresent to false.
691-
// b. Set smallestUnit to "nanosecond".
692-
let smallest_unit = smallest_unit.unwrap_or(TemporalUnit::Nanosecond);
693-
694-
// 18. Let existingLargestUnit be ! DefaultTemporalLargestUnit(duration.[[Years]],
695-
// duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]],
696-
// duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]],
697-
// duration.[[Microseconds]]).
698-
let existing_largest_unit = self.default_largest_unit();
699-
700-
// 19. Let defaultLargestUnit be LargerOfTwoTemporalUnits(existingLargestUnit, smallestUnit).
701-
let default_largest = existing_largest_unit.max(smallest_unit);
702-
703-
// 20. If largestUnit is undefined, then
704-
// a. Set largestUnitPresent to false.
705-
// b. Set largestUnit to defaultLargestUnit.
706-
// 21. Else if largestUnit is "auto", then
707-
// a. Set largestUnit to defaultLargestUnit.
708-
let largest_unit = match largest_unit {
709-
Some(TemporalUnit::Auto) | None => default_largest,
710-
Some(unit) => unit,
711-
};
712-
713-
// 23. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
714-
if largest_unit.max(smallest_unit) != largest_unit {
715-
return Err(TemporalError::range().with_message(
716-
"largestUnit when rounding Duration was not the largest provided unit",
717-
));
718-
}
719-
720-
// 24. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
721-
let maximum = smallest_unit.to_maximum_rounding_increment();
722-
// 25. If maximum is not undefined, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
723-
if let Some(max) = maximum {
724-
increment.validate(max.into(), false)?;
725-
}
726-
727-
// 26. Let hoursToDaysConversionMayOccur be false.
728-
// 27. If duration.[[Days]] ≠ 0 and zonedRelativeTo is not undefined, set hoursToDaysConversionMayOccur to true.
729-
// 28. Else if abs(duration.[[Hours]]) ≥ 24, set hoursToDaysConversionMayOccur to true.
730-
let hours_to_days_may_occur =
731-
(self.days() != 0.0 && relative_to.zdt.is_some()) || self.hours().abs() >= 24.0;
732-
733-
// 29. If smallestUnit is "nanosecond" and roundingIncrement = 1, let roundingGranularityIsNoop
734-
// be true; else let roundingGranularityIsNoop be false.
735-
let is_noop =
736-
smallest_unit == TemporalUnit::Nanosecond && increment == RoundingIncrement::ONE;
737-
// 30. If duration.[[Years]] = 0 and duration.[[Months]] = 0 and duration.[[Weeks]] = 0,
738-
// let calendarUnitsPresent be false; else let calendarUnitsPresent be true.
739-
let calendar_units_present =
740-
!(self.years() == 0.0 && self.months() == 0.0 && self.weeks() == 0.0);
741-
742-
// 31. If roundingGranularityIsNoop is true, and largestUnit is existingLargestUnit, and calendarUnitsPresent is false,
743-
// and hoursToDaysConversionMayOccur is false, and abs(duration.[[Minutes]]) < 60, and abs(duration.[[Seconds]]) < 60,
744-
// and abs(duration.[[Milliseconds]]) < 1000, and abs(duration.[[Microseconds]]) < 1000, and abs(duration.[[Nanoseconds]]) < 1000, then
745-
if is_noop
746-
&& largest_unit == existing_largest_unit
747-
&& !calendar_units_present
748-
&& !hours_to_days_may_occur
749-
&& self.minutes().abs() < 60.0
750-
&& self.seconds().abs() < 60.0
751-
&& self.milliseconds() < 1000.0
752-
&& self.microseconds() < 1000.0
753-
&& self.nanoseconds() < 1000.0
754-
{
755-
// a. NOTE: The above conditions mean that the operation will have no effect: the
756-
// smallest unit and rounding increment will leave the total duration unchanged,
757-
// and it can be determined without calling a calendar or time zone method that
758-
// no balancing will take place.
759-
// b. Return ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]],
760-
// duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]],
761-
// duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]],
762-
// duration.[[Nanoseconds]]).
763-
return Ok(*self);
764-
}
765-
766-
// 32. Let precalculatedPlainDateTime be undefined.
767-
// 33. If roundingGranularityIsNoop is false, or IsCalendarUnit(largestUnit) is true, or largestUnit is "day",
768-
// or calendarUnitsPresent is true, or duration.[[Days]] ≠ 0, let plainDateTimeOrRelativeToWillBeUsed be true;
769-
// else let plainDateTimeOrRelativeToWillBeUsed be false.
770-
let pdtr_will_be_used = !is_noop
771-
|| largest_unit.is_calendar_unit()
772-
|| largest_unit == TemporalUnit::Day
773-
|| calendar_units_present
774-
|| self.days() == 0.0;
775-
776-
// 34. If zonedRelativeTo is not undefined and plainDateTimeOrRelativeToWillBeUsed is true, then
777-
let precalculated = if relative_to.zdt.is_some() && pdtr_will_be_used {
778-
return Err(TemporalError::general("Not yet implemented."));
779-
// a. NOTE: The above conditions mean that the corresponding Temporal.PlainDateTime or
780-
// Temporal.PlainDate for zonedRelativeTo will be used in one of the operations below.
781-
// b. Let instant be ! CreateTemporalInstant(zonedRelativeTo.[[Nanoseconds]]).
782-
// c. Set precalculatedPlainDateTime to ? GetPlainDateTimeFor(timeZoneRec, instant, zonedRelativeTo.[[Calendar]]).
783-
// d. Set plainRelativeTo to ! CreateTemporalDate(precalculatedPlainDateTime.[[ISOYear]],
784-
// precalculatedPlainDateTime.[[ISOMonth]], precalculatedPlainDateTime.[[ISODay]], zonedRelativeTo.[[Calendar]]).
785-
} else {
786-
None
787-
};
788-
// 35. Let calendarRec be ? CreateCalendarMethodsRecordFromRelativeTo(plainRelativeTo, zonedRelativeTo, « DATE-ADD, DATE-UNTIL »).
789-
790-
// TODO: relativeTo will need to be removed soon.
791-
let relative_to_date = relative_to.date;
792-
793-
// 36. Let unbalanceResult be ? UnbalanceDateDurationRelative(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], largestUnit, plainRelativeTo, calendarRec).
794-
let unbalanced = self
795-
.date()
796-
.unbalance_relative(largest_unit, relative_to_date)?;
797-
798-
// NOTE: Step 37 handled in round duration
799-
// 37. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]],
800-
// duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
801-
// 38. Let roundRecord be ? RoundDuration(unbalanceResult.[[Years]], unbalanceResult.[[Months]],
802-
// unbalanceResult.[[Weeks]], unbalanceResult.[[Days]], norm, roundingIncrement, smallestUnit,
803-
// roundingMode, plainRelativeTo, calendarRec, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
804-
let (round_result, _) = Self::new_unchecked(unbalanced, *self.time()).round_internal(
805-
increment,
806-
smallest_unit,
807-
mode,
808-
relative_to,
809-
precalculated,
810-
)?;
811-
812-
// 39. Let roundResult be roundRecord.[[NormalizedDuration]].
813-
// 40. If zonedRelativeTo is not undefined, then
814-
let balance_result = if relative_to.zdt.is_some() {
815-
return Err(TemporalError::general("Not yet implemented."));
816-
// a. Set roundResult to ? AdjustRoundedDurationDays(roundResult.[[Years]], roundResult.[[Months]],
817-
// roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[NormalizedTime]], roundingIncrement,
818-
// smallestUnit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, precalculatedPlainDateTime).
819-
// b. Let balanceResult be ? BalanceTimeDurationRelative(roundResult.[[Days]],
820-
// roundResult.[[NormalizedTime]], largestUnit, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
821-
// 41. Else,
822-
} else {
823-
// NOTE: DateDuration::round will always return a NormalizedTime::default as per spec.
824-
// a. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundResult.[[NormalizedTime]], roundResult.[[Days]]).
825-
let norm_with_days = round_result.0 .1.add_days(round_result.0 .0.days as i64)?;
826-
// b. Let balanceResult be BalanceTimeDuration(normWithDays, largestUnit).
827-
TimeDuration::from_normalized(norm_with_days, largest_unit)?
828-
};
829-
830-
// 42. Let result be ? BalanceDateDurationRelative(roundResult.[[Years]],
831-
// roundResult.[[Months]], roundResult.[[Weeks]], balanceResult.[[Days]],
832-
// largestUnit, smallestUnit, plainRelativeTo, calendarRec).
833-
let intermediate = DateDuration::new_unchecked(
834-
round_result.0 .0.years,
835-
round_result.0 .0.months,
836-
round_result.0 .0.weeks,
837-
balance_result.0,
838-
);
839-
let result =
840-
intermediate.balance_relative(largest_unit, smallest_unit, relative_to_date)?;
841-
842-
// 43. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]],
843-
// result.[[Weeks]], result.[[Days]], balanceResult.[[Hours]], balanceResult.[[Minutes]],
844-
// balanceResult.[[Seconds]], balanceResult.[[Milliseconds]], balanceResult.[[Microseconds]],
845-
// balanceResult.[[Nanoseconds]]).
846-
Self::new(
847-
result.years,
848-
result.months,
849-
result.weeks,
850-
result.days,
851-
balance_result.1.hours,
852-
balance_result.1.minutes,
853-
balance_result.1.seconds,
854-
balance_result.1.milliseconds,
855-
balance_result.1.microseconds,
856-
balance_result.1.nanoseconds,
857-
)
858-
}
859613
}
860614

861615
// TODO: Update, optimize, and fix the below. is_valid_duration should probably be generic over a T.

0 commit comments

Comments
 (0)