@@ -9,7 +9,7 @@ use crate::{
9
9
use ixdtf:: parsers:: { records:: TimeDurationRecord , IsoDurationParser } ;
10
10
use std:: str:: FromStr ;
11
11
12
- use self :: normalized:: { NormalizedDurationRecord , NormalizedTimeDuration } ;
12
+ use self :: normalized:: NormalizedTimeDuration ;
13
13
14
14
mod date;
15
15
pub ( crate ) mod normalized;
@@ -357,58 +357,6 @@ impl Duration {
357
357
}
358
358
}
359
359
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
-
412
360
// ==== Public Duration methods ====
413
361
414
362
impl Duration {
@@ -449,7 +397,7 @@ impl Duration {
449
397
}
450
398
451
399
#[ inline]
452
- pub fn round_v2 (
400
+ pub fn round (
453
401
& self ,
454
402
increment : Option < RoundingIncrement > ,
455
403
smallest_unit : Option < TemporalUnit > ,
@@ -647,7 +595,9 @@ impl Duration {
647
595
) ?;
648
596
// d. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundRecord.[[NormalizedDuration]].[[NormalizedTime]],
649
597
// 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 ) ?;
651
601
// e. Let balanceResult be ? BalanceTimeDuration(normWithDays, largestUnit).
652
602
let ( balanced_days, balanced_time) =
653
603
TimeDuration :: from_normalized ( norm_with_days, largest_unit) ?;
@@ -660,202 +610,6 @@ impl Duration {
660
610
// 41. Return ? CreateTemporalDuration(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[Hours]], roundResult.[[Minutes]], roundResult.[[Seconds]], roundResult.[[Milliseconds]], roundResult.[[Microseconds]], roundResult.[[Nanoseconds]]).
661
611
Ok ( round_result)
662
612
}
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
- }
859
613
}
860
614
861
615
// TODO: Update, optimize, and fix the below. is_valid_duration should probably be generic over a T.
0 commit comments