Intl.NumberFormat V3 S4
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2023
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案通过添加范围格式化、基于枚举的分组选项、新的舍入和精度控制、对十进制字符串的支持、额外的舍入模式以及新的 signDisplay 值来增强 Intl.NumberFormat。它旨在满足常见的客户端需求,并借鉴了 CLDR/ICU 中的现有实践。4、Chrome 106 和 Firefox 93 中发布。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMA-402 提案:Intl.NumberFormat V3
状态:第 3 阶段(截至 2021 年 7 月)
Intl.NumberFormat 最初在最初的 Intl 规范中被添加。最近,ECMA-402 提案 Unified Intl.NumberFormat 添加了几个新的关键特性。这个我称之为“Intl.NumberFormat V3”的提案是另一批特性,这些特性已被证明对该 API 的客户端很重要。
动机
在 ECMA-402 中,我们每年收到数十个特性请求。在形成这个提案时,作者(sffc)考虑了所有与 Intl.NumberFormat 相关的特性请求,并将它们与以下标准进行了对比:
- 该特性必须有多个利益相关者。
- 该特性必须有健全的先前实践,例如在 CLDR、ICU 或 Unicode 中。
- 该特性必须难以在用户层面实现(例如依赖于区域数据)。
本提案的所有部分都符合这一标准,而且作者的意图是,所有符合该标准的 Intl.NumberFormat 特性请求都是本提案的一部分。
特性
formatRange (ECMA-402 #393)
这部分是仿照 Intl.DateTimeFormat.prototype.formatRange
提案设计的。它涉及到在 Intl.NumberFormat 原型上添加一个新函数 .formatRange(),并大体遵循 Intl.DateTimeFormat 中 .formatRange() 引入的语义。
还将添加对等方法:
Intl.NumberFormat.prototype.formatRangeToPartsIntl.PluralRules.prototype.selectRange(#16)
例如:
这里将采用 Intl.DateTimeFormat 的 formatToParts 语义:各个部分将获得一个 source 属性,其值将为 "shared"、"startRange" 或 "endRange"。
当范围的两侧在四舍五入后解析为相同的值时,将添加一个约等于符号。约等于符号会附加在数字上,并同时附加减号或加号(如适用)。(#10、#11、#13)
如果第二个参数小于第一个参数,或者任一参数是 NaN,则抛出错误。(#12)
特性检测
分组枚举 (ECMA-402 #367)
主要议题:#3
目前,Intl.NumberFormat 接受一个 { useGrouping } 选项,该选项接受一个布尔值。然而,正如在错误线程中报告的,用户在指定分组时可能想要几个选项。本提案旨在使以下内容成为 { useGrouping } 的有效输入:
false:不显示分组分隔符"min2":当一组中至少有 2 位数字时显示分组分隔符;例如,“1000”(第一组太小)和“10,000”(现在该组中至少有 2 位数字)。(Bikeshed:#23)"auto"(默认):根据区域偏好显示分组分隔符,这也可能取决于货币。大多数区域偏好使用分组分隔符。"always":即使区域偏好不使用分组分隔符,也显示分组分隔符。true:"always"的别名。undefined(默认):"auto"的别名。
在 resolvedOptions 中,将返回 false 或三个字符串之一。这是一个可观察的行为变化,因为目前只返回布尔值 true 和 false。
特性检测
新的舍入/精度选项 (ECMA-402 #286)
主要议题:#8
以下附加选项被提议添加到 Intl.NumberFormat 选项对象中,以控制舍入行为:
roundingPriority= 一个字符串,设置为"auto"、"morePrecision"或"lessPrecision"(详情见下文)roundingIncrement= 以下列表中的数字:« 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 »- 镍币舍入:
{ minimumFractionDigits: 2, maximumFractionDigits: 2, roundingIncrement: 5 } - 一角硬币舍入:
{ minimumFractionDigits: 2, maximumFractionDigits: 2, roundingIncrement: 10 }
- 镍币舍入:
trailingZeroDisplay= 一个字符串,表示在整数上显示尾随零的策略:"auto"= 当前行为。根据minimumFractionDigits和minimumSignificantDigits保留尾随零。"stripIfInteger"= 与"auto"相同,但如果小数位均为零,则移除小数位。
roundingIncrement 不能与有效数字舍入或除 "auto" 之外的任何 roundingPriority 设置混合使用。
舍入优先级
目前,Intl.NumberFormat 允许两种舍入策略:最小/最大小数位,或最小/最大有效数字。目前,如果同时指定了最小/最大小数位和最小/最大有效数字,则有效数字设置优先,小数位设置被忽略。
新的 roundingPriority 选项指定了两种新策略来解决混合小数位和有效数字设置的问题。为了更好地表达新策略,请考虑以下选项对象:
上述选项应被解释为:
- 在百分位舍入数字
- 在第二个有效数字之后舍入数字
现在,考虑数字“4.321”。maximumFractionDigits 希望在百分位舍入,产生“4.32”。然而,maximumSignificantDigits 希望在两个有效数字之后舍入,产生“4.3”。因此我们存在冲突。
新的设置 roundingPriority 提供了如何解决此冲突的提示。有三个选项:
roundingPriority: "auto"意味着有效数字在冲突中总是获胜。roundingPriority: "morePrecision"意味着精度更高的结果在冲突中获胜。roundingPriority: "lessPrecision"意味着精度更低的结果在冲突中获胜。
整个结果是原子性的,包括尾随零。例如:
考虑输入数字“1”。minimumFractionDigits 希望保留尾随零直到百分位,产生“1.00”,而 minimumSignificantDigits 希望只保留渲染两个有效数字所需的位数,产生“1.0”。然而,由于 maximumSignificantDigits 具有更高的精度(舍入到 10^-5,而不是小数精度的 10^-2),解析后的答案是“1.0”。
特性检测
将字符串解释为十进制数 (ECMA-402 #334)
format() 方法目前接受一个数字或一个 BigInt,而字符串被解释为数字。这部分提议将字符串重新定义为十进制数而不是数字。
一个常见的用例是将货币金额存储为小单位(如分)的 BigInt。此 API 可用于保留 BigInt 的全部精度:
十进制字符串的一般语法,基本上是 #.#E#,是计算中广泛理解的格式。我们使用的具体版本是 ECMA-262 StringNumericLiteral 语法,它允许非十进制数字,如十六进制和二进制。
任意精度十进制字符串旨在作为格式化的直通使用。推动者并不打算让字符串成为 ECMAScript 中数字计算的事实标准。对于通用的任意精度十进制类型,请参见 Decimal 提案。
特性检测
舍入模式 (ECMA-402 #419)
主要议题:#7
Intl.NumberFormat 总是执行“四舍五入”(例如,如果你有 2.5,它会被舍入到 3)。然而,我们知道有用户和用例会受益于暴露更多舍入模式选项。
提议的舍入模式列表是:
- ceil(向 +∞ 舍入)
- floor(向 -∞ 舍入)
- expand(远离 0 舍入)
- trunc(向 0 舍入)
- halfCeil(平局时向 +∞ 舍入)
- halfFloor(平局时向 -∞ 舍入)
- halfExpand(平局时远离 0 舍入;当前行为;默认值)
- halfTrunc(平局时向 0 舍入)
- halfEven(平局时向具有偶数值的值舍入)
这些模式的行为将反映 ICU 用户指南,其中“expand”映射到 ICU 的“UP”,“trunc”映射到 ICU 的“DOWN”。
舍入不会查看或更改数字的符号位。因此,-0 和 0 在舍入方面是等效的。(#21)
特性检测
负数符号显示
主要议题:#17
根据客户的反馈,提议了一个新选项 signDisplay: "negative"。新选项的行为将类似于 "auto",只是符号不会显示在负零上。
特性检测
实现状态
已在以下环境中发布:
- Safari 15.4
- Chrome 106
- Firefox 93