@@ -908,41 +908,6 @@ impl<C: DateFieldsResolver> ArithmeticDate<C> {
908908 balanced. into_checked ( ) . ok_or ( DateAddError :: Overflow )
909909 }
910910
911- /// Implements the Temporal operation `NonISODateAdd`, but without any bounds checks.
912- ///
913- /// For internal use by `until()` where the operation is known to succeed.
914- /// Follows `Overflow::Constrain` logic.
915- fn added_without_checks ( & self , duration : DateDuration , cal : & C ) -> UncheckedArithmeticDate < C > {
916- let extended_year = duration. add_years_to ( self . year ( ) . to_extended_year ( ) ) ;
917- let y0 = cal. year_info_from_extended ( extended_year) ;
918- let base_month = cal. month_from_ordinal ( self . year ( ) , self . month ( ) ) ;
919- let m0 = cal
920- . ordinal_from_month (
921- y0,
922- base_month,
923- DateFromFieldsOptions {
924- overflow : Some ( Overflow :: Constrain ) ,
925- ..Default :: default ( )
926- } ,
927- )
928- . unwrap_or ( 0 ) ;
929-
930- let end_of_month = Self :: new_balanced ( y0, duration. add_months_to ( m0) + 1 , 0 , cal) ;
931- let base_day = self . day ( ) ;
932- let regulated_day = if base_day <= end_of_month. day {
933- base_day
934- } else {
935- end_of_month. day
936- } ;
937-
938- Self :: new_balanced (
939- end_of_month. year ,
940- i64:: from ( end_of_month. ordinal_month ) ,
941- duration. add_weeks_and_days_to ( regulated_day) ,
942- cal,
943- )
944- }
945-
946911 /// Implements the Temporal abstract operation `NonISODateUntil`.
947912 ///
948913 /// This takes two dates (`self` and `other`), then returns a duration that, when
@@ -1080,16 +1045,25 @@ impl<C: DateFieldsResolver> ArithmeticDate<C> {
10801045 }
10811046 }
10821047
1083- // Now that we have `years`, `months`, and `weeks`, we can compute
1084- // `days` directly by subtracting RD values of the intermediate date
1085- // (self + YMW) and the target date (`other`).
1086- let from_date = self . added_without_checks (
1087- DateDuration :: from_signed_ymwd ( years, months, weeks, 0 ) ,
1048+ // 1. Let _days_ be 0.
1049+ // 1. Let _candidateDays_ be _sign_.
1050+ // 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _months_, _weeks_, _candidateDays_) is *false*,
1051+ // 1. Set _days_ to _candidateDays_.
1052+ // 1. Set _candidateDays_ to _candidateDays_ + _sign_.
1053+ let mut days = 0 ;
1054+ // There is no pressing need to optimize candidate_days here: the early-return RD arithmetic
1055+ // optimization will be hit if the largest_unit is weeks/days, and if it is months or years we will
1056+ // arrive here with a candidate date that is at most 31 days off. We can run this loop 31 times.
1057+ let mut candidate_days = sign;
1058+ while !self . surpasses (
1059+ other,
1060+ DateDuration :: from_signed_ymwd ( years, months, weeks, candidate_days) ,
1061+ sign,
10881062 cal,
1089- ) ;
1090- let from = C :: to_rata_die_inner ( from_date . year , from_date . ordinal_month , from_date . day ) ;
1091- let to = other . to_rata_die ( ) ;
1092- let days = to - from ;
1063+ ) {
1064+ days = candidate_days ;
1065+ candidate_days += sign ;
1066+ }
10931067
10941068 // 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_).
10951069 DateDuration :: from_signed_ymwd ( years, months, weeks, days)
0 commit comments