@@ -8,16 +8,20 @@ use crate::{
8
8
duration:: DateDuration ,
9
9
DateTime , Duration ,
10
10
} ,
11
- iso:: { IsoDate , IsoDateSlots , IsoDateTime } ,
11
+ iso:: { IsoDate , IsoDateSlots , IsoDateTime , IsoTime } ,
12
12
options:: {
13
- ArithmeticOverflow , RelativeTo , RoundingIncrement , TemporalRoundingMode , TemporalUnit ,
13
+ ArithmeticOverflow , DifferenceOperation , DifferenceSettings , ResolvedRoundingOptions ,
14
+ TemporalUnit ,
14
15
} ,
15
16
parsers:: parse_date_time,
16
17
TemporalError , TemporalFields , TemporalResult , TemporalUnwrap ,
17
18
} ;
18
19
use std:: str:: FromStr ;
19
20
20
- use super :: { duration:: TimeDuration , MonthDay , Time , YearMonth } ;
21
+ use super :: {
22
+ duration:: { normalized:: NormalizedDurationRecord , TimeDuration } ,
23
+ MonthDay , Time , YearMonth ,
24
+ } ;
21
25
22
26
/// The native Rust implementation of `Temporal.PlainDate`.
23
27
#[ non_exhaustive]
@@ -37,14 +41,6 @@ impl Date {
37
41
Self { iso, calendar }
38
42
}
39
43
40
- #[ inline]
41
- /// Returns a new moved date and the days associated with that adjustment
42
- pub ( crate ) fn move_relative_date ( & self , duration : & Duration ) -> TemporalResult < ( Self , f64 ) > {
43
- let new_date = self . add_date ( duration, None ) ?;
44
- let days = f64:: from ( self . days_until ( & new_date) ) ;
45
- Ok ( ( new_date, days) )
46
- }
47
-
48
44
/// Returns the date after adding the given duration to date.
49
45
///
50
46
/// Temporal Equivalent: 3.5.13 `AddDate ( calendar, plainDate, duration [ , options [ , dateAdd ] ] )`
@@ -112,20 +108,15 @@ impl Date {
112
108
}
113
109
114
110
/// Equivalent: DifferenceTemporalPlainDate
115
- #[ allow( clippy:: too_many_arguments) ]
116
111
pub ( crate ) fn diff_date (
117
112
& self ,
118
- op : bool ,
113
+ op : DifferenceOperation ,
119
114
other : & Self ,
120
- rounding_mode : Option < TemporalRoundingMode > ,
121
- rounding_increment : Option < RoundingIncrement > ,
122
- largest_unit : Option < TemporalUnit > ,
123
- smallest_unit : Option < TemporalUnit > ,
115
+ settings : DifferenceSettings ,
124
116
) -> TemporalResult < Duration > {
125
117
// 1. If operation is SINCE, let sign be -1. Otherwise, let sign be 1.
126
118
// 2. Set other to ? ToTemporalDate(other).
127
119
128
- // TODO(improvement): Implement `PartialEq` for `TemporalCalendar`
129
120
// 3. If ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception.
130
121
if self . calendar ( ) . identifier ( ) ? != other. calendar ( ) . identifier ( ) ? {
131
122
return Err ( TemporalError :: range ( )
@@ -134,20 +125,12 @@ impl Date {
134
125
135
126
// 4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
136
127
// 5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, DATE, « », "day", "day").
137
- let rounding_increment = rounding_increment. unwrap_or_default ( ) ;
138
- let ( sign, rounding_mode) = if op {
139
- (
140
- -1.0 ,
141
- rounding_mode
142
- . unwrap_or ( TemporalRoundingMode :: Trunc )
143
- . negate ( ) ,
144
- )
145
- } else {
146
- ( 1.0 , rounding_mode. unwrap_or ( TemporalRoundingMode :: Trunc ) )
147
- } ;
148
- let smallest_unit = smallest_unit. unwrap_or ( TemporalUnit :: Day ) ;
149
- // Use the defaultlargestunit which is max smallestlargestdefault and smallestunit
150
- let largest_unit = largest_unit. unwrap_or ( smallest_unit. max ( TemporalUnit :: Day ) ) ;
128
+ let ( sign, resolved) = ResolvedRoundingOptions :: from_diff_settings (
129
+ settings,
130
+ op,
131
+ TemporalUnit :: Day ,
132
+ TemporalUnit :: Day ,
133
+ ) ?;
151
134
152
135
// 6. If temporalDate.[[ISOYear]] = other.[[ISOYear]], and temporalDate.[[ISOMonth]] = other.[[ISOMonth]],
153
136
// and temporalDate.[[ISODay]] = other.[[ISODay]], then
@@ -159,62 +142,39 @@ impl Date {
159
142
// 7. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « DATE-ADD, DATE-UNTIL »).
160
143
// 8. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]).
161
144
// 9. Let result be ? DifferenceDate(calendarRec, temporalDate, other, resolvedOptions).
162
- let result = self . internal_diff_date ( other, largest_unit) ?;
163
-
164
- // 10. If settings.[[SmallestUnit]] is "day" and settings.[[RoundingIncrement]] = 1,
165
- // let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
166
- let is_noop =
167
- smallest_unit == TemporalUnit :: Day && rounding_increment == RoundingIncrement :: ONE ;
168
-
169
- // 12. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], sign × result.[[Weeks]], sign × result.[[Days]], 0, 0, 0, 0, 0, 0).
170
- if is_noop {
171
- return Duration :: new (
172
- result. years ( ) * sign,
173
- result. months ( ) * sign,
174
- result. weeks ( ) * sign,
175
- result. days ( ) * sign,
176
- 0.0 ,
177
- 0.0 ,
178
- 0.0 ,
179
- 0.0 ,
180
- 0.0 ,
181
- 0.0 ,
145
+ let result = self . internal_diff_date ( other, resolved. largest_unit ) ?;
146
+
147
+ // 10. Let duration be ! CreateNormalizedDurationRecord(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], ZeroTimeDuration()).
148
+ let duration = NormalizedDurationRecord :: from_date_duration ( * result. date ( ) ) ?;
149
+ // 11. If settings.[[SmallestUnit]] is "day" and settings.[[RoundingIncrement]] = 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
150
+ let rounding_granularity_is_noop =
151
+ resolved. smallest_unit == TemporalUnit :: Day && resolved. increment . get ( ) == 1 ;
152
+ // 12. If roundingGranularityIsNoop is false, then
153
+ let date_duration = if !rounding_granularity_is_noop {
154
+ // a. Let destEpochNs be GetUTCEpochNanoseconds(other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], 0, 0, 0, 0, 0, 0).
155
+ let dest_epoch_ns = other. iso . as_nanoseconds ( ) . temporal_unwrap ( ) ?;
156
+ // b. Let dateTime be ISO Date-Time Record { [[Year]]: temporalDate.[[ISOYear]], [[Month]]: temporalDate.[[ISOMonth]], [[Day]]: temporalDate.[[ISODay]], [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0 }.
157
+ let dt = DateTime :: new_unchecked (
158
+ IsoDateTime :: new_unchecked ( self . iso , IsoTime :: default ( ) ) ,
159
+ self . calendar . clone ( ) ,
182
160
) ;
183
- }
161
+ // c. Set duration to ? RoundRelativeDuration(duration, destEpochNs, dateTime, calendarRec, unset, settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
162
+ * duration
163
+ . round_relative_duration ( dest_epoch_ns, & dt, None , resolved) ?
164
+ . 0
165
+ . date ( )
166
+ } else {
167
+ duration. date ( )
168
+ } ;
184
169
185
- // 11. If roundingGranularityIsNoop is false, then
186
- // a. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], result.[[Weeks]],
187
- // result.[[Days]], ZeroTimeDuration(), settings.[[RoundingIncrement]], settings.[[SmallestUnit]],
188
- // settings.[[RoundingMode]], temporalDate, calendarRec).
189
- // TODO: Look into simplifying round_internal's parameters.
190
- let round_record = result. round_internal (
191
- rounding_increment,
192
- smallest_unit,
193
- rounding_mode,
194
- & RelativeTo {
195
- zdt : None ,
196
- date : Some ( self ) ,
197
- } ,
198
- None ,
199
- ) ?;
200
- // b. Let roundResult be roundRecord.[[NormalizedDuration]].
201
- let round_result = round_record. 0 . 0 . 0 ;
202
- // c. Set result to ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]],
203
- // roundResult.[[Days]], settings.[[LargestUnit]], settings.[[SmallestUnit]], temporalDate, calendarRec).
204
- let result = round_result. balance_relative ( largest_unit, smallest_unit, Some ( self ) ) ?;
205
-
206
- Duration :: new (
207
- result. years * sign,
208
- result. months * sign,
209
- result. weeks * sign,
210
- result. days * sign,
211
- 0.0 ,
212
- 0.0 ,
213
- 0.0 ,
214
- 0.0 ,
215
- 0.0 ,
216
- 0.0 ,
217
- )
170
+ let sign = f64:: from ( sign as i8 ) ;
171
+ // 13. Return ! CreateTemporalDuration(sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], 0, 0, 0, 0, 0, 0).
172
+ Ok ( Duration :: from_date_duration ( & DateDuration :: new (
173
+ date_duration. years * sign,
174
+ date_duration. months * sign,
175
+ date_duration. weeks * sign,
176
+ date_duration. days * sign,
177
+ ) ?) )
218
178
}
219
179
}
220
180
@@ -303,40 +263,12 @@ impl Date {
303
263
self . add_date ( & duration. negated ( ) , overflow)
304
264
}
305
265
306
- pub fn until (
307
- & self ,
308
- other : & Self ,
309
- rounding_mode : Option < TemporalRoundingMode > ,
310
- rounding_increment : Option < RoundingIncrement > ,
311
- smallest_unit : Option < TemporalUnit > ,
312
- largest_unit : Option < TemporalUnit > ,
313
- ) -> TemporalResult < Duration > {
314
- self . diff_date (
315
- false ,
316
- other,
317
- rounding_mode,
318
- rounding_increment,
319
- smallest_unit,
320
- largest_unit,
321
- )
266
+ pub fn until ( & self , other : & Self , settings : DifferenceSettings ) -> TemporalResult < Duration > {
267
+ self . diff_date ( DifferenceOperation :: Until , other, settings)
322
268
}
323
269
324
- pub fn since (
325
- & self ,
326
- other : & Self ,
327
- rounding_mode : Option < TemporalRoundingMode > ,
328
- rounding_increment : Option < RoundingIncrement > ,
329
- smallest_unit : Option < TemporalUnit > ,
330
- largest_unit : Option < TemporalUnit > ,
331
- ) -> TemporalResult < Duration > {
332
- self . diff_date (
333
- true ,
334
- other,
335
- rounding_mode,
336
- rounding_increment,
337
- smallest_unit,
338
- largest_unit,
339
- )
270
+ pub fn since ( & self , other : & Self , settings : DifferenceSettings ) -> TemporalResult < Duration > {
271
+ self . diff_date ( DifferenceOperation :: Since , other, settings)
340
272
}
341
273
}
342
274
@@ -582,23 +514,31 @@ mod tests {
582
514
fn simple_date_until ( ) {
583
515
let earlier = Date :: from_str ( "1969-07-24" ) . unwrap ( ) ;
584
516
let later = Date :: from_str ( "1969-10-05" ) . unwrap ( ) ;
585
- let result = earlier. until ( & later, None , None , None , None ) . unwrap ( ) ;
517
+ let result = earlier
518
+ . until ( & later, DifferenceSettings :: default ( ) )
519
+ . unwrap ( ) ;
586
520
assert_eq ! ( result. days( ) , 73.0 , ) ;
587
521
588
522
let later = Date :: from_str ( "1996-03-03" ) . unwrap ( ) ;
589
- let result = earlier. until ( & later, None , None , None , None ) . unwrap ( ) ;
523
+ let result = earlier
524
+ . until ( & later, DifferenceSettings :: default ( ) )
525
+ . unwrap ( ) ;
590
526
assert_eq ! ( result. days( ) , 9719.0 , ) ;
591
527
}
592
528
593
529
#[ test]
594
530
fn simple_date_since ( ) {
595
531
let earlier = Date :: from_str ( "1969-07-24" ) . unwrap ( ) ;
596
532
let later = Date :: from_str ( "1969-10-05" ) . unwrap ( ) ;
597
- let result = later. since ( & earlier, None , None , None , None ) . unwrap ( ) ;
533
+ let result = later
534
+ . since ( & earlier, DifferenceSettings :: default ( ) )
535
+ . unwrap ( ) ;
598
536
assert_eq ! ( result. days( ) , 73.0 , ) ;
599
537
600
538
let later = Date :: from_str ( "1996-03-03" ) . unwrap ( ) ;
601
- let result = later. since ( & earlier, None , None , None , None ) . unwrap ( ) ;
539
+ let result = later
540
+ . since ( & earlier, DifferenceSettings :: default ( ) )
541
+ . unwrap ( ) ;
602
542
assert_eq ! ( result. days( ) , 9719.0 , ) ;
603
543
}
604
544
0 commit comments