Skip to content

Commit d47fdaf

Browse files
authored
Implement add and subtract methods for Duration (#74)
Related to ongoing work for #11 As it says in the title, implementing the add and subtract methods for duration.
1 parent 7430431 commit d47fdaf

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/components/duration.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,48 @@ impl Duration {
400400
}
401401
}
402402

403+
/// Returns the result of adding a `Duration` to the current `Duration`
404+
#[inline]
405+
pub fn add(&self, other: &Self) -> TemporalResult<Self> {
406+
// NOTE: Implemented from AddDurations
407+
// Steps 1-22 are functionally useless in this context.
408+
409+
// 23. Let largestUnit1 be DefaultTemporalLargestUnit(y1, mon1, w1, d1, h1, min1, s1, ms1, mus1).
410+
let largest_one = self.default_largest_unit();
411+
// 24. Let largestUnit2 be DefaultTemporalLargestUnit(y2, mon2, w2, d2, h2, min2, s2, ms2, mus2).
412+
let largest_two = other.default_largest_unit();
413+
// 25. Let largestUnit be LargerOfTwoTemporalUnits(largestUnit1, largestUnit2).
414+
let largest_unit = largest_one.max(largest_two);
415+
// 26. Let norm1 be NormalizeTimeDuration(h1, min1, s1, ms1, mus1, ns1).
416+
let norm_one = NormalizedTimeDuration::from_time_duration(self.time());
417+
// 27. Let norm2 be NormalizeTimeDuration(h2, min2, s2, ms2, mus2, ns2).
418+
let norm_two = NormalizedTimeDuration::from_time_duration(other.time());
419+
420+
// 28. If IsCalendarUnit(largestUnit), throw a RangeError exception.
421+
if largest_unit.is_calendar_unit() {
422+
return Err(TemporalError::range().with_message(
423+
"Largest unit cannot be a calendar unit when adding two durations.",
424+
));
425+
}
426+
427+
// 29. Let normResult be ? AddNormalizedTimeDuration(norm1, norm2).
428+
// 30. Set normResult to ? Add24HourDaysToNormalizedTimeDuration(normResult, d1 + d2).
429+
let result = (norm_one + norm_two)?.add_days((self.days() + other.days()) as i64)?;
430+
431+
// 31. Let result be ? BalanceTimeDuration(normResult, largestUnit).
432+
let (result_days, result_time) = TimeDuration::from_normalized(result, largest_unit)?;
433+
434+
// 32. Return ! CreateTemporalDuration(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]],
435+
// result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
436+
Ok(Duration::from_day_and_time(result_days, &result_time))
437+
}
438+
439+
/// Returns the result of subtracting a `Duration` from the current `Duration`
440+
#[inline]
441+
pub fn subtract(&self, other: &Self) -> TemporalResult<Self> {
442+
self.add(&other.negated())
443+
}
444+
403445
#[inline]
404446
pub fn round(
405447
&self,

src/components/duration/tests.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,31 @@ fn rounding_increment_non_integer() {
463463
&[0.0, 0.0, 0.0, 1e9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
464464
);
465465
}
466+
467+
#[test]
468+
fn basic_add_duration() {
469+
let base = Duration::new(0.0, 0.0, 0.0, 1.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0).unwrap();
470+
let other = Duration::new(0.0, 0.0, 0.0, 2.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0).unwrap();
471+
let result = base.add(&other).unwrap();
472+
assert_eq!(result.days(), 3.0);
473+
assert_eq!(result.minutes(), 10.0);
474+
475+
let other = Duration::new(0.0, 0.0, 0.0, -3.0, 0.0, -15.0, 0.0, 0.0, 0.0, 0.0).unwrap();
476+
let result = base.add(&other).unwrap();
477+
assert_eq!(result.days(), -2.0);
478+
assert_eq!(result.minutes(), -10.0);
479+
}
480+
481+
#[test]
482+
fn basic_subtract_duration() {
483+
let base = Duration::new(0.0, 0.0, 0.0, 3.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0).unwrap();
484+
let other = Duration::new(0.0, 0.0, 0.0, 1.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0).unwrap();
485+
let result = base.subtract(&other).unwrap();
486+
assert_eq!(result.days(), 2.0);
487+
assert_eq!(result.minutes(), 10.0);
488+
489+
let other = Duration::new(0.0, 0.0, 0.0, -3.0, 0.0, -15.0, 0.0, 0.0, 0.0, 0.0).unwrap();
490+
let result = base.subtract(&other).unwrap();
491+
assert_eq!(result.days(), 6.0);
492+
assert_eq!(result.minutes(), 30.0);
493+
}

0 commit comments

Comments
 (0)