Skip to content

Commit 6541d2b

Browse files
committed
attempt at fixing TotalTimeDuration
1 parent adb16c6 commit 6541d2b

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

src/builtins/core/duration/normalized.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,13 @@ impl NormalizedTimeDuration {
200200
/// Equivalent: 7.5.31 TotalTimeDuration ( timeDuration, unit )
201201
/// TODO Fix: Arithemtic on floating point numbers is not safe. According to NOTE 2 in the spec
202202
pub(crate) fn total(&self, unit: TemporalUnit) -> TemporalResult<FiniteF64> {
203-
let time_duration = FiniteF64::try_from(self.0)?;
203+
let time_duration = self.0;
204204
// 1. Let divisor be the value in the "Length in Nanoseconds" column of the row of Table 21 whose "Value" column contains unit.
205205
let unit_nanoseconds = unit.as_nanoseconds().temporal_unwrap()?;
206-
let divisor = FiniteF64::try_from(unit_nanoseconds)?;
207206
// 2. NOTE: The following step cannot be implemented directly using floating-point arithmetic when 𝔽(timeDuration) is not a safe integer.
208207
// The division can be implemented in C++ with the __float128 type if the compiler supports it, or with software emulation such as in the SoftFP library.
209208
// 3. Return timeDuration / divisor.
210-
time_duration.checked_div(&divisor)
209+
DurationTotal::new(time_duration, unit_nanoseconds).to_fractional_total()
211210
}
212211

213212
/// Round the current `NormalizedTimeDuration`.
@@ -249,6 +248,32 @@ impl Add<Self> for NormalizedTimeDuration {
249248
}
250249
}
251250

251+
// Struct to handle division steps in `TotalTimeDuration`
252+
struct DurationTotal {
253+
quotient: i128,
254+
remainder: i128,
255+
unit_nanoseconds: u64,
256+
}
257+
258+
impl DurationTotal {
259+
pub fn new(time_duration: i128, unit_nanoseconds: u64) -> Self {
260+
let quotient = time_duration.div_euclid(unit_nanoseconds as i128);
261+
let remainder = time_duration.rem_euclid(unit_nanoseconds as i128);
262+
263+
Self {
264+
quotient,
265+
remainder,
266+
unit_nanoseconds,
267+
}
268+
}
269+
270+
pub(crate) fn to_fractional_total(&self) -> TemporalResult<FiniteF64> {
271+
let fractional = FiniteF64::try_from(self.remainder)?
272+
.checked_div(&FiniteF64::try_from(self.unit_nanoseconds)?)?;
273+
FiniteF64::try_from(self.quotient)?.checked_add(&fractional)
274+
}
275+
}
276+
252277
// ==== NormalizedDurationRecord ====
253278
//
254279
// A record consisting of a DateDuration and NormalizedTimeDuration

0 commit comments

Comments
 (0)