Skip to content

Commit a891242

Browse files
committed
Update Duration's inner representation from floating point to integers. (#268)
This begins to address #189 and closes #250. This completely updates the inner representation for `Duration`, migrating from `FiniteF64`s to `i64`. Due to the change there were also some fairly robust changes across the internals for `Duration`. There were also some related updates made to some parts of rounding to bring it more in line with the specification and also calculate values without needing fractional values.
1 parent 70474d0 commit a891242

32 files changed

Lines changed: 1294 additions & 1298 deletions

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/builtins/compiled/duration/tests.rs

Lines changed: 325 additions & 313 deletions
Large diffs are not rendered by default.

src/builtins/core/calendar.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,10 @@ impl Calendar {
337337
duration.years(),
338338
duration.months(),
339339
duration.weeks(),
340-
duration.days().checked_add(&balance_days)?,
340+
duration
341+
.days()
342+
.checked_add(balance_days)
343+
.ok_or(TemporalError::range())?,
341344
),
342345
overflow,
343346
)?;
@@ -954,22 +957,22 @@ mod tests {
954957
let second = IsoDate::new_unchecked(test.1 .0, test.1 .1, test.1 .2);
955958
let result = calendar.date_until(&first, &second, Unit::Year).unwrap();
956959
assert_eq!(
957-
result.years().0 as i32,
960+
result.years() as i32,
958961
test.2 .0,
959962
"year failed for test \"{test:?}\""
960963
);
961964
assert_eq!(
962-
result.months().0 as i32,
965+
result.months() as i32,
963966
test.2 .1,
964967
"months failed for test \"{test:?}\""
965968
);
966969
assert_eq!(
967-
result.weeks().0 as i32,
970+
result.weeks() as i32,
968971
test.2 .2,
969972
"weeks failed for test \"{test:?}\""
970973
);
971974
assert_eq!(
972-
result.days().0 as i32,
975+
result.days(),
973976
test.2 .3,
974977
"days failed for test \"{test:?}\""
975978
);

src/builtins/core/date.rs

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use crate::{
1111
DisplayCalendar, ResolvedRoundingOptions, Unit, UnitGroup,
1212
},
1313
parsers::{parse_date_time, IxdtfStringBuilder},
14-
primitive::FiniteF64,
1514
provider::{NeverProvider, TimeZoneProvider},
1615
MonthCode, TemporalError, TemporalResult, TemporalUnwrap, TimeZone,
1716
};
@@ -217,10 +216,7 @@ impl PlainDate {
217216
// 2. If options is not present, set options to undefined.
218217
let overflow = overflow.unwrap_or(ArithmeticOverflow::Constrain);
219218
// 3. If duration.[[Years]] ≠ 0, or duration.[[Months]] ≠ 0, or duration.[[Weeks]] ≠ 0, then
220-
if duration.date().years != 0.0
221-
|| duration.date().months != 0.0
222-
|| duration.date().weeks != 0.0
223-
{
219+
if duration.date().years != 0 || duration.date().months != 0 || duration.date().weeks != 0 {
224220
// a. If dateAdd is not present, then
225221
// i. Set dateAdd to unused.
226222
// ii. If calendar is an Object, set dateAdd to ? GetMethod(calendar, "dateAdd").
@@ -235,20 +231,17 @@ impl PlainDate {
235231
// duration.[[Nanoseconds]]).
236232
// 6. Let days be duration.[[Days]] + BalanceTimeDuration(norm,
237233
// "day").[[Days]].
238-
let days = duration.days().checked_add(
239-
&TimeDuration::from_normalized(duration.time().to_normalized(), Unit::Day)?.0,
240-
)?;
234+
let days = duration
235+
.days()
236+
.checked_add(
237+
TimeDuration::from_normalized(duration.time().to_normalized(), Unit::Day)?.0,
238+
)
239+
.ok_or(TemporalError::range())?;
241240

242241
// 7. Let result be ? AddISODate(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], 0, 0, 0, days, overflow).
243-
let result = self.iso.add_date_duration(
244-
&DateDuration::new(
245-
FiniteF64::default(),
246-
FiniteF64::default(),
247-
FiniteF64::default(),
248-
days,
249-
)?,
250-
overflow,
251-
)?;
242+
let result = self
243+
.iso
244+
.add_date_duration(&DateDuration::new(0, 0, 0, days)?, overflow)?;
252245

253246
Self::try_new(
254247
result.year,
@@ -276,12 +269,7 @@ impl PlainDate {
276269

277270
if largest_unit == Unit::Day {
278271
let days = self.days_until(other);
279-
return Ok(Duration::from(DateDuration::new(
280-
FiniteF64::default(),
281-
FiniteF64::default(),
282-
FiniteF64::default(),
283-
FiniteF64::from(days),
284-
)?));
272+
return Ok(Duration::from(DateDuration::new(0, 0, 0, days.into())?));
285273
}
286274

287275
self.calendar()
@@ -911,13 +899,13 @@ mod tests {
911899
let result = earlier
912900
.until(&later, DifferenceSettings::default())
913901
.unwrap();
914-
assert_eq!(result.days(), 73.0,);
902+
assert_eq!(result.days(), 73,);
915903

916904
let later = PlainDate::from_str("1996-03-03").unwrap();
917905
let result = earlier
918906
.until(&later, DifferenceSettings::default())
919907
.unwrap();
920-
assert_eq!(result.days(), 9719.0,);
908+
assert_eq!(result.days(), 9719,);
921909
}
922910

923911
#[test]
@@ -927,13 +915,13 @@ mod tests {
927915
let result = later
928916
.since(&earlier, DifferenceSettings::default())
929917
.unwrap();
930-
assert_eq!(result.days(), 73.0,);
918+
assert_eq!(result.days(), 73,);
931919

932920
let later = PlainDate::from_str("1996-03-03").unwrap();
933921
let result = later
934922
.since(&earlier, DifferenceSettings::default())
935923
.unwrap();
936-
assert_eq!(result.days(), 9719.0,);
924+
assert_eq!(result.days(), 9719,);
937925
}
938926

939927
#[test]

src/builtins/core/datetime.rs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ impl PlainDateTime {
199199
let diff = self
200200
.iso
201201
.diff(&other.iso, &self.calendar, options.largest_unit)?;
202-
203202
// 4. If smallestUnit is nanosecond and roundingIncrement = 1, return diff.
204203
if options.smallest_unit == Unit::Nanosecond && options.increment.get() == 1 {
205204
return Ok(diff);
@@ -799,7 +798,6 @@ mod tests {
799798
ToStringRoundingOptions, Unit,
800799
},
801800
parsers::Precision,
802-
primitive::FiniteF64,
803801
MonthCode, TemporalResult,
804802
};
805803

@@ -1031,15 +1029,7 @@ mod tests {
10311029

10321030
let result = pdt
10331031
.add(
1034-
&Duration::from(
1035-
DateDuration::new(
1036-
FiniteF64::default(),
1037-
FiniteF64(1.0),
1038-
FiniteF64::default(),
1039-
FiniteF64::default(),
1040-
)
1041-
.unwrap(),
1042-
),
1032+
&Duration::from(DateDuration::new(0, 1, 0, 0).unwrap()),
10431033
None,
10441034
)
10451035
.unwrap();
@@ -1057,15 +1047,7 @@ mod tests {
10571047

10581048
let result = pdt
10591049
.subtract(
1060-
&Duration::from(
1061-
DateDuration::new(
1062-
FiniteF64::default(),
1063-
FiniteF64(1.0),
1064-
FiniteF64::default(),
1065-
FiniteF64::default(),
1066-
)
1067-
.unwrap(),
1068-
),
1050+
&Duration::from(DateDuration::new(0, 1, 0, 0).unwrap()),
10691051
None,
10701052
)
10711053
.unwrap();
@@ -1081,13 +1063,13 @@ mod tests {
10811063
PlainDateTime::try_new(2019, 10, 29, 10, 46, 38, 271, 986, 102, Calendar::default())
10821064
.unwrap();
10831065

1084-
let result = dt.subtract(&Duration::hour(FiniteF64(12.0)), None).unwrap();
1066+
let result = dt.subtract(&Duration::hour(12), None).unwrap();
10851067
assert_datetime(
10861068
result,
10871069
(2019, 10, tinystr!(4, "M10"), 28, 22, 46, 38, 271, 986, 102),
10881070
);
10891071

1090-
let result = dt.add(&Duration::hour(FiniteF64(-12.0)), None).unwrap();
1072+
let result = dt.add(&Duration::hour(-12), None).unwrap();
10911073
assert_datetime(
10921074
result,
10931075
(2019, 10, tinystr!(4, "M10"), 28, 22, 46, 38, 271, 986, 102),
@@ -1119,15 +1101,15 @@ mod tests {
11191101
let settings = create_diff_setting(Unit::Hour, 3, RoundingMode::HalfExpand);
11201102
let result = earlier.until(&later, settings).unwrap();
11211103

1122-
assert_eq!(result.days(), 973.0);
1123-
assert_eq!(result.hours(), 3.0);
1104+
assert_eq!(result.days(), 973);
1105+
assert_eq!(result.hours(), 3);
11241106

11251107
let settings = create_diff_setting(Unit::Minute, 30, RoundingMode::HalfExpand);
11261108
let result = earlier.until(&later, settings).unwrap();
11271109

1128-
assert_eq!(result.days(), 973.0);
1129-
assert_eq!(result.hours(), 4.0);
1130-
assert_eq!(result.minutes(), 30.0);
1110+
assert_eq!(result.days(), 973);
1111+
assert_eq!(result.hours(), 4);
1112+
assert_eq!(result.minutes(), 30);
11311113
}
11321114

11331115
#[test]
@@ -1142,15 +1124,15 @@ mod tests {
11421124
let settings = create_diff_setting(Unit::Hour, 3, RoundingMode::HalfExpand);
11431125
let result = later.since(&earlier, settings).unwrap();
11441126

1145-
assert_eq!(result.days(), 973.0);
1146-
assert_eq!(result.hours(), 3.0);
1127+
assert_eq!(result.days(), 973);
1128+
assert_eq!(result.hours(), 3);
11471129

11481130
let settings = create_diff_setting(Unit::Minute, 30, RoundingMode::HalfExpand);
11491131
let result = later.since(&earlier, settings).unwrap();
11501132

1151-
assert_eq!(result.days(), 973.0);
1152-
assert_eq!(result.hours(), 4.0);
1153-
assert_eq!(result.minutes(), 30.0);
1133+
assert_eq!(result.days(), 973);
1134+
assert_eq!(result.hours(), 4);
1135+
assert_eq!(result.minutes(), 30);
11541136
}
11551137

11561138
#[test]

0 commit comments

Comments
 (0)