mirror of https://github.com/tc39/test262.git
Use simplified PartitionDurationFormatPattern to computed expected results
This commit is contained in:
parent
4da0b8f005
commit
71091f1541
|
@ -29,6 +29,8 @@ defines:
|
|||
- getDateTimeComponents
|
||||
- getDateTimeComponentValues
|
||||
- isCanonicalizedStructurallyValidTimeZoneName
|
||||
- partitionDurationFormatPattern
|
||||
- formatDurationFormatPattern
|
||||
---*/
|
||||
/**
|
||||
*/
|
||||
|
@ -2502,3 +2504,212 @@ function isCanonicalizedStructurallyValidTimeZoneName(timeZone) {
|
|||
}
|
||||
return zoneNamePattern.test(timeZone);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description Simplified PartitionDurationFormatPattern implementation which
|
||||
* only supports the "en" locale.
|
||||
* @param {Object} duration the duration record
|
||||
* @param {String} style the duration format style
|
||||
* @result {Array} an array with formatted duration parts
|
||||
*/
|
||||
|
||||
function partitionDurationFormatPattern(duration, style = "short") {
|
||||
const units = [
|
||||
"years",
|
||||
"months",
|
||||
"weeks",
|
||||
"days",
|
||||
"hours",
|
||||
"minutes",
|
||||
"seconds",
|
||||
"milliseconds",
|
||||
"microseconds",
|
||||
"nanoseconds",
|
||||
];
|
||||
|
||||
function durationToFractionalSeconds(duration) {
|
||||
let {
|
||||
seconds = 0,
|
||||
milliseconds = 0,
|
||||
microseconds = 0,
|
||||
nanoseconds = 0,
|
||||
} = duration;
|
||||
|
||||
// Directly return seconds when no sub-seconds are present.
|
||||
if (milliseconds === 0 && microseconds === 0 && nanoseconds === 0) {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
// Otherwise compute the overall amount of nanoseconds using BigInt to avoid
|
||||
// loss of precision.
|
||||
let ns_sec = BigInt(seconds) * 1_000_000_000n;
|
||||
let ns_ms = BigInt(milliseconds) * 1_000_000n;
|
||||
let ns_us = BigInt(microseconds) * 1_000n;
|
||||
let ns = ns_sec + ns_ms + ns_us + BigInt(nanoseconds);
|
||||
|
||||
// Split the nanoseconds amount into seconds and sub-seconds.
|
||||
let q = ns / 1_000_000_000n;
|
||||
let r = ns % 1_000_000_000n;
|
||||
|
||||
// Pad sub-seconds, without any leading negative sign, to nine digits.
|
||||
if (r < 0) {
|
||||
r = -r;
|
||||
}
|
||||
r = String(r).padStart(9, "0");
|
||||
|
||||
// Return seconds with fractional part as a decimal string.
|
||||
return `${q}.${r}`;
|
||||
}
|
||||
|
||||
// Only "en" is supported.
|
||||
const locale = "en";
|
||||
const numberingSystem = "latn";
|
||||
const timeSeparator = ":";
|
||||
|
||||
let result = [];
|
||||
let separated = false;
|
||||
|
||||
for (let unit of units) {
|
||||
// Absent units default to zero.
|
||||
let value = duration[unit] ?? 0;
|
||||
|
||||
let display = "auto";
|
||||
if (style === "digital") {
|
||||
// Always display numeric units per GetDurationUnitOptions.
|
||||
if (unit === "hours" || unit === "minutes" || unit === "seconds") {
|
||||
display = "always";
|
||||
}
|
||||
|
||||
// Numeric seconds and sub-seconds are combined into a single value.
|
||||
if (unit === "seconds") {
|
||||
value = durationToFractionalSeconds(duration);
|
||||
}
|
||||
}
|
||||
|
||||
// "auto" display omits zero units.
|
||||
if (value !== 0 || display !== "auto") {
|
||||
// Map the DurationFormat style to a NumberFormat style.
|
||||
let unitStyle = style;
|
||||
if (style === "digital") {
|
||||
if (unit === "hours") {
|
||||
unitStyle = "numeric";
|
||||
} else if (unit === "minutes" || unit === "seconds") {
|
||||
unitStyle = "2-digit";
|
||||
} else {
|
||||
unitStyle = "short";
|
||||
}
|
||||
}
|
||||
|
||||
// NumberFormat requires singular unit names.
|
||||
let numberFormatUnit = unit.slice(0, -1);
|
||||
|
||||
// Compute the matching NumberFormat options.
|
||||
let nfOpts;
|
||||
if (unitStyle !== "numeric" && unitStyle !== "2-digit") {
|
||||
// The value is formatted as a standalone unit.
|
||||
nfOpts = {
|
||||
numberingSystem,
|
||||
style: "unit",
|
||||
unit: numberFormatUnit,
|
||||
unitDisplay: unitStyle,
|
||||
};
|
||||
} else {
|
||||
let roundingMode = undefined;
|
||||
let minimumFractionDigits = undefined;
|
||||
let maximumFractionDigits = undefined;
|
||||
|
||||
// Numeric seconds include any sub-seconds.
|
||||
if (style === "digital" && unit === "seconds") {
|
||||
roundingMode = "trunc";
|
||||
minimumFractionDigits = 0;
|
||||
maximumFractionDigits = 9;
|
||||
}
|
||||
|
||||
// The value is formatted as a numeric unit.
|
||||
nfOpts = {
|
||||
numberingSystem,
|
||||
minimumIntegerDigits: (unitStyle === "2-digit" ? 2 : 1),
|
||||
roundingMode,
|
||||
minimumFractionDigits,
|
||||
maximumFractionDigits,
|
||||
};
|
||||
}
|
||||
|
||||
let nf = new Intl.NumberFormat(locale, nfOpts);
|
||||
let formatted = nf.formatToParts(value);
|
||||
|
||||
// Add |numberFormatUnit| to the formatted number.
|
||||
let list = [];
|
||||
for (let {value, type} of formatted) {
|
||||
list.push({type, value, unit: numberFormatUnit});
|
||||
}
|
||||
|
||||
if (!separated) {
|
||||
// Prepend the separator before the next numeric unit.
|
||||
if (unitStyle === "2-digit" || unitStyle === "numeric") {
|
||||
separated = true;
|
||||
}
|
||||
|
||||
// Append the formatted number to |result|.
|
||||
result.push(list);
|
||||
} else {
|
||||
let last = result[result.length - 1];
|
||||
|
||||
// Prepend the time separator before the formatted number.
|
||||
last.push({
|
||||
type: "literal",
|
||||
value: timeSeparator,
|
||||
});
|
||||
|
||||
// Concatenate |last| and the formatted number.
|
||||
last.push(...list);
|
||||
}
|
||||
} else {
|
||||
separated = false;
|
||||
}
|
||||
|
||||
// No further units possible after "seconds" when style is "digital".
|
||||
if (style === "digital" && unit === "seconds") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let lf = new Intl.ListFormat(locale, {
|
||||
type: "unit",
|
||||
style: (style !== "digital" ? style : "short"),
|
||||
});
|
||||
|
||||
// Collect all formatted units into a list of strings.
|
||||
let strings = [];
|
||||
for (let parts of result) {
|
||||
let string = "";
|
||||
for (let {value} of parts) {
|
||||
string += value;
|
||||
}
|
||||
strings.push(string);
|
||||
}
|
||||
|
||||
// Format the list of strings and compute the overall result.
|
||||
let flattened = [];
|
||||
for (let {type, value} of lf.formatToParts(strings)) {
|
||||
if (type === "element") {
|
||||
flattened.push(...result.shift());
|
||||
} else {
|
||||
flattened.push({type, value});
|
||||
}
|
||||
}
|
||||
return flattened;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description Return the formatted string from partitionDurationFormatPattern.
|
||||
* @param {Object} duration the duration record
|
||||
* @param {String} style the duration format style
|
||||
* @result {String} a string containing the formatted duration
|
||||
*/
|
||||
|
||||
function formatDurationFormatPattern(duration, style) {
|
||||
return partitionDurationFormatPattern(duration, style).reduce((acc, e) => acc + e.value, "");
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
esid: sec-Intl.DurationFormat.prototype.format
|
||||
description: Test if format method formats duration correctly with different "style" arguments
|
||||
locale: [en-US]
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -21,7 +22,7 @@ const duration = {
|
|||
nanoseconds: 9,
|
||||
};
|
||||
|
||||
const expected = formatDurationFormatPattern(duration);
|
||||
|
||||
const df = new Intl.DurationFormat("en");
|
||||
const expected = "1 yr, 2 mths, 3 wks, 3 days, 4 hr, 5 min, 6 sec, 7 ms, 8 μs, 9 ns";
|
||||
assert.sameValue(df.format(duration), expected, `Assert DurationFormat format output using default style option`);
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
esid: sec-Intl.DurationFormat.prototype.format
|
||||
description: Test if format method formats duration correctly with different "style" arguments
|
||||
locale: [en-US]
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
const style = "digital";
|
||||
const expected = "1 yr, 2 mths, 3 wks, 3 days, 4:05:06";
|
||||
|
||||
const duration = {
|
||||
years: 1,
|
||||
|
@ -25,5 +25,7 @@ const duration = {
|
|||
nanoseconds: 9,
|
||||
};
|
||||
|
||||
const expected = formatDurationFormatPattern(duration, style);
|
||||
|
||||
const df = new Intl.DurationFormat("en", {style});
|
||||
assert.sameValue(df.format(duration), expected, `Assert DurationFormat format output using ${style} style option`);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
esid: sec-Intl.DurationFormat.prototype.format
|
||||
description: Test if format method formats duration correctly with different "style" arguments
|
||||
locale: [en-US]
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
const style = "long";
|
||||
const expected = "1 year, 2 months, 3 weeks, 3 days, 4 hours, 5 minutes, 6 seconds, 7 milliseconds, 8 microseconds, 9 nanoseconds";
|
||||
|
||||
const duration = {
|
||||
years: 1,
|
||||
|
@ -24,5 +24,7 @@ const duration = {
|
|||
nanoseconds: 9,
|
||||
};
|
||||
|
||||
const expected = formatDurationFormatPattern(duration, style);
|
||||
|
||||
const df = new Intl.DurationFormat("en", {style});
|
||||
assert.sameValue(df.format(duration), expected, `Assert DurationFormat format output using ${style} style option`);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
esid: sec-Intl.DurationFormat.prototype.format
|
||||
description: Test if format method formats duration correctly with different "style" arguments
|
||||
locale: [en-US]
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
const style = "narrow";
|
||||
const expected = "1y 2m 3w 3d 4h 5m 6s 7ms 8μs 9ns";
|
||||
|
||||
const duration = {
|
||||
years: 1,
|
||||
|
@ -24,5 +24,7 @@ const duration = {
|
|||
nanoseconds: 9,
|
||||
};
|
||||
|
||||
const expected = formatDurationFormatPattern(duration, style);
|
||||
|
||||
const df = new Intl.DurationFormat("en", {style});
|
||||
assert.sameValue(df.format(duration), expected, `Assert DurationFormat format output using ${style} style option`);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
esid: sec-Intl.DurationFormat.prototype.format
|
||||
description: Test if format method formats duration correctly with different "style" arguments
|
||||
locale: [en-US]
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
const style = "short";
|
||||
const expected = "1 yr, 2 mths, 3 wks, 3 days, 4 hr, 5 min, 6 sec, 7 ms, 8 μs, 9 ns";
|
||||
|
||||
const duration = {
|
||||
years: 1,
|
||||
|
@ -24,5 +24,7 @@ const duration = {
|
|||
nanoseconds: 9,
|
||||
};
|
||||
|
||||
const expected = formatDurationFormatPattern(duration, style);
|
||||
|
||||
const df = new Intl.DurationFormat("en", {style});
|
||||
assert.sameValue(df.format(duration), expected, `Assert DurationFormat format output using ${style} style option`);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/*---
|
||||
esid: sec-Intl.DurationFormat.prototype.formatToParts
|
||||
description: Checks basic handling of formatToParts, using long, short,narrow and digital styles.
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -37,31 +38,7 @@ const duration = {
|
|||
nanoseconds: 789,
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{ type: "integer", value: "7", unit: "hour" },
|
||||
{ type: "literal", value: " ", unit: "hour" },
|
||||
{ type: "unit", value: "hr", unit: "hour" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "8", unit: "minute" },
|
||||
{ type: "literal", value: " ", unit: "minute" },
|
||||
{ type: "unit", value: "min", unit: "minute" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "9", unit: "second" },
|
||||
{ type: "literal", value: " ", unit: "second" },
|
||||
{ type: "unit", value: "sec", unit: "second" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "123", unit: "millisecond" },
|
||||
{ type: "literal", value: " ", unit: "millisecond" },
|
||||
{ type: "unit", value: "ms", unit: "millisecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "456", unit: "microsecond" },
|
||||
{ type: "literal", value: " ", unit: "microsecond" },
|
||||
{ type: "unit", value: "μs", unit: "microsecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "789", unit: "nanosecond" },
|
||||
{ type: "literal", value: " ", unit: "nanosecond" },
|
||||
{ type: "unit", value: "ns", unit: "nanosecond" },
|
||||
];
|
||||
const expected = partitionDurationFormatPattern(duration);
|
||||
|
||||
let df = new Intl.DurationFormat('en');
|
||||
compare(df.formatToParts(duration), expected, `Using style : default`);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/*---
|
||||
esid: sec-Intl.DurationFormat.prototype.formatToParts
|
||||
description: Checks basic handling of formatToParts, using long, short,narrow and digital styles.
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -38,13 +39,8 @@ const duration = {
|
|||
};
|
||||
|
||||
const style = "digital";
|
||||
const expected = [
|
||||
{ type: "integer", value: "7", unit: "hour" },
|
||||
{ type: "literal", value: ":"},
|
||||
{ type: "integer", value: "08", unit: "minute" },
|
||||
{ type: "literal", value: ":"},
|
||||
{ type: "integer", value: "09", unit: "second" },
|
||||
];
|
||||
|
||||
const expected = partitionDurationFormatPattern(duration, style);
|
||||
|
||||
let df = new Intl.DurationFormat('en', { style });
|
||||
compare(df.formatToParts(duration), expected, `Using style : ${style}`);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/*---
|
||||
esid: sec-Intl.DurationFormat.prototype.formatToParts
|
||||
description: Checks basic handling of formatToParts, using long, short,narrow and digital styles.
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -38,31 +39,8 @@ const duration = {
|
|||
};
|
||||
|
||||
const style = "long";
|
||||
const expected = [
|
||||
{ type: "integer", value: "7", unit: "hour" },
|
||||
{ type: "literal", value: " ", unit: "hour" },
|
||||
{ type: "unit", value: "hours", unit: "hour" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "8", unit: "minute" },
|
||||
{ type: "literal", value: " ", unit: "minute" },
|
||||
{ type: "unit", value: "minutes", unit: "minute" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "9", unit: "second" },
|
||||
{ type: "literal", value: " ", unit: "second" },
|
||||
{ type: "unit", value: "seconds", unit: "second" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "123", unit: "millisecond" },
|
||||
{ type: "literal", value: " ", unit: "millisecond" },
|
||||
{ type: "unit", value: "milliseconds", unit: "millisecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "456", unit: "microsecond" },
|
||||
{ type: "literal", value: " ", unit: "microsecond" },
|
||||
{ type: "unit", value: "microseconds", unit: "microsecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "789", unit: "nanosecond" },
|
||||
{ type: "literal", value: " ", unit: "nanosecond" },
|
||||
{ type: "unit", value: "nanoseconds", unit: "nanosecond" },
|
||||
];
|
||||
|
||||
const expected = partitionDurationFormatPattern(duration, style);
|
||||
|
||||
let df = new Intl.DurationFormat('en', { style });
|
||||
compare(df.formatToParts(duration), expected, `Using style : ${style}`);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/*---
|
||||
esid: sec-Intl.DurationFormat.prototype.formatToParts
|
||||
description: Checks basic handling of formatToParts, using long, short,narrow and digital styles.
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -38,25 +39,8 @@ const duration = {
|
|||
};
|
||||
|
||||
const style = "narrow";
|
||||
const expected = [
|
||||
{ type: "integer", value: "7", unit: "hour" },
|
||||
{ type: "unit", value: "h", unit: "hour" },
|
||||
{ type: "literal", value: " " },
|
||||
{ type: "integer", value: "8", unit: "minute" },
|
||||
{ type: "unit", value: "m", unit: "minute" },
|
||||
{ type: "literal", value: " " },
|
||||
{ type: "integer", value: "9", unit: "second" },
|
||||
{ type: "unit", value: "s", unit: "second" },
|
||||
{ type: "literal", value: " " },
|
||||
{ type: "integer", value: "123", unit: "millisecond" },
|
||||
{ type: "unit", value: "ms", unit: "millisecond" },
|
||||
{ type: "literal", value: " " },
|
||||
{ type: "integer", value: "456", unit: "microsecond" },
|
||||
{ type: "unit", value: "μs", unit: "microsecond" },
|
||||
{ type: "literal", value: " " },
|
||||
{ type: "integer", value: "789", unit: "nanosecond" },
|
||||
{ type: "unit", value: "ns", unit: "nanosecond" },
|
||||
];
|
||||
|
||||
const expected = partitionDurationFormatPattern(duration, style);
|
||||
|
||||
let df = new Intl.DurationFormat('en', { style });
|
||||
compare(df.formatToParts(duration), expected, `Using style : ${style}`);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
/*---
|
||||
esid: sec-Intl.DurationFormat.prototype.formatToParts
|
||||
description: Checks basic handling of formatToParts, using long, short,narrow and digital styles.
|
||||
includes: [testIntl.js]
|
||||
features: [Intl.DurationFormat]
|
||||
---*/
|
||||
|
||||
|
@ -38,31 +39,8 @@ const duration = {
|
|||
};
|
||||
|
||||
const style = "short";
|
||||
const expected = [
|
||||
{ type: "integer", value: "7", unit: "hour" },
|
||||
{ type: "literal", value: " ", unit: "hour" },
|
||||
{ type: "unit", value: "hr", unit: "hour" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "8", unit: "minute" },
|
||||
{ type: "literal", value: " ", unit: "minute" },
|
||||
{ type: "unit", value: "min", unit: "minute" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "9", unit: "second" },
|
||||
{ type: "literal", value: " ", unit: "second" },
|
||||
{ type: "unit", value: "sec", unit: "second" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "123", unit: "millisecond" },
|
||||
{ type: "literal", value: " ", unit: "millisecond" },
|
||||
{ type: "unit", value: "ms", unit: "millisecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "456", unit: "microsecond" },
|
||||
{ type: "literal", value: " ", unit: "microsecond" },
|
||||
{ type: "unit", value: "μs", unit: "microsecond" },
|
||||
{ type: "literal", value: ", " },
|
||||
{ type: "integer", value: "789", unit: "nanosecond" },
|
||||
{ type: "literal", value: " ", unit: "nanosecond" },
|
||||
{ type: "unit", value: "ns", unit: "nanosecond" },
|
||||
];
|
||||
|
||||
const expected = partitionDurationFormatPattern(duration, style);
|
||||
|
||||
let df = new Intl.DurationFormat('en', { style });
|
||||
compare(df.formatToParts(duration), expected, `Using style : ${style}`);
|
||||
|
|
Loading…
Reference in New Issue