LibJS: Correctly display a negative sign on negative durations

This is a normative change in the Intl.DurationFormat proposal. See:
https://github.com/tc39/proposal-intl-duration-format/commit/adfc4a1
This commit is contained in:
Timothy Flynn 2024-08-13 13:03:17 -04:00 committed by Andreas Kling
parent 300f8d3dbb
commit 72f61396cd
Notes: github-actions[bot] 2024-08-14 09:49:05 +00:00
2 changed files with 47 additions and 8 deletions

View file

@ -615,7 +615,7 @@ Vector<DurationFormatPart> format_numeric_seconds(VM& vm, DurationFormat const&
return result;
}
// 1.1.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed )
// 1.1.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ), https://tc39.es/proposal-intl-duration-format/#sec-formatnumericunits
Vector<DurationFormatPart> format_numeric_units(VM& vm, DurationFormat const& duration_format, Temporal::DurationRecord const& duration, StringView first_numeric_unit, bool sign_displayed)
{
// 1. Assert: firstNumericUnit is "hours", "minutes", or "seconds".
@ -685,20 +685,38 @@ Vector<DurationFormatPart> format_numeric_units(VM& vm, DurationFormat const& du
// 16. If hoursFormatted is true, then
if (hours_formatted) {
// a. Append FormatNumericHours(durationFormat, hoursValue, signDisplayed) to numericPartsList.
// a. If signDisplayed is true, then
if (sign_displayed) {
// i. If hoursValue is 0 and DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]) is -1, then
if (hours_value == 0 && Temporal::duration_sign(duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds) == -1) {
// 1. Set hoursValue to negative-zero.
hours_value = -0.0;
}
}
// b. Append FormatNumericHours(durationFormat, hoursValue, signDisplayed) to numericPartsList.
numeric_parts_list.extend(format_numeric_hours(vm, duration_format, hours_value, sign_displayed));
// b. Set signDisplayed to false.
sign_displayed = hours_value < 0;
// c. Set signDisplayed to false.
sign_displayed = false;
}
// 17. If minutesFormatted is true, then
if (minutes_formatted) {
// a. Append FormatNumericMinutes(durationFormat, minutesValue, hoursFormatted, signDisplayed) to numericPartsList.
// a. If signDisplayed is true, then
if (sign_displayed) {
// i. If minutesValue is 0 and DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]) is -1, then
if (minutes_value == 0 && Temporal::duration_sign(duration.years, duration.months, duration.weeks, duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds, duration.microseconds, duration.nanoseconds) == -1) {
// 1. Set minutesValue to negative-zero.
minutes_value = -0.0;
}
}
// b. Append FormatNumericMinutes(durationFormat, minutesValue, hoursFormatted, signDisplayed) to numericPartsList.
numeric_parts_list.extend(format_numeric_minutes(vm, duration_format, minutes_value, hours_formatted, sign_displayed));
// b. Set signDisplayed to false.
sign_displayed = minutes_value < 0;
// c. Set signDisplayed to false.
sign_displayed = false;
}
// 18. If secondsFormatted is true, then
@ -707,7 +725,7 @@ Vector<DurationFormatPart> format_numeric_units(VM& vm, DurationFormat const& du
numeric_parts_list.extend(format_numeric_seconds(vm, duration_format, seconds_value, minutes_formatted, sign_displayed));
// b. Set signDisplayed to false.
sign_displayed = seconds_value < 0;
sign_displayed = false;
}
// 19. Return numericPartsList.

View file

@ -110,6 +110,27 @@ describe("correct behavior", () => {
const lt = new Intl.DurationFormat("lt", { style: "digital" });
expect(lt.format(duration)).toBe("01:02:03");
});
test("negative duration fields", () => {
const duration = {
years: -1,
months: -2,
weeks: -3,
days: -4,
hours: -5,
minutes: -6,
seconds: -7,
milliseconds: -8,
microseconds: -9,
nanoseconds: -11,
};
const en = new Intl.DurationFormat("en", { style: "digital" });
expect(en.format(duration)).toBe("-1 yr, 2 mths, 3 wks, 4 days, 5:06:07.008009011");
const de = new Intl.DurationFormat("de", { style: "digital" });
expect(de.format(duration)).toBe("-1 J, 2 Mon., 3 Wo., 4 Tg. und 5:06:07,008009011");
});
});
describe("errors", () => {