Intl.RelativeTimeFormat S4
中文标题:Intl.RelativeTimeFormat API 规范 [草案]
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2020
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了一个新的 Intl API,Intl.RelativeTimeFormat,用于以区域设置敏感的方式格式化相对时间值。它通过提供一个接受数字和单位的低级 API,解决了当前许多库实现的相对时间格式化的标准化需求。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Intl.RelativeTimeFormat API 规范 [草案]
概述
动机
由于普遍使用,相对时间格式化值存在于大多数网站中,并且可用于大多数框架(例如,React,通过 react-intl 和 react-globalize;Ember,通过 ember-intl)。流行的本地化库如 Moment.js、Format.js、Globalize 和 其他 也已经实现了相对时间值的格式化过程。
当前大多数相对时间格式化实现很可能需要大量的 CLDR 原始数据或编译数据来格式化相对时间值。将其引入平台将提高 Web 性能和开发人员生产力,因为他们不再需要为了格式化相对时间值而引入额外的负担。
使用示例
以下示例展示了如何使用英语创建相对时间格式化器。
单位:"year"(年)、"quarter"(季度)、"month"(月)、"week"(周)、"day"(日)、"hour"(小时)、"minute"(分钟)和 "second"(秒)。
注意:如果传入
numeric:auto选项,它将产生字符串yesterday或tomorrow,而不是1 day ago或in 1 day,这允许输出中不必总是使用数值。
实现状态
阶段 4
实现进展
- V8 v7.1.179,随 Chrome 71 发布
- 随 Firefox 65 发布
- Polyfills 可用
- 浏览器兼容性
反向指针
Polyfills
有几种可用的 polyfill,它们列在下面的比较表中。所有 polyfill 在 API 方面的功能相同:它们仅在实现细节上有所不同,例如 polyfill 的导入方式、区域设置的加载方式,或者实现是否通过官方 ECMAScript 一致性测试 以完全覆盖所有可能的边缘情况。
作者
- Caridy Patiño (@caridy)
- Eric Ferraiuolo (@ericf)
- Zibi Braniecki (@zbraniecki)
- Rafael Xavier (@rxaviers)
- Daniel Ehrenberg (@littledan)
审阅者
待定
提案
Intl.RelativeTimeFormat 是一个低级 API,通过提供日期和时间字段的国际化消息(在可用时使用惯用词或短语),帮助库和框架以本地化方式格式化相对时间。
规范
技术设计
本提案基于 ICU 相对日期时间格式化器以及 Unicode CLDR 日历字段相对值:
- http://icu-project.org/apiref/icu4j/com/ibm/icu/text/RelativeDateTimeFormatter.html
- https://unicode.org/reports/tr35/tr35-dates.html#Calendar_Fields
它还基于 LDML 规范,C.11 语言复数规则:
先例
Java
- ICU:
com.ibm.icu.impl.RelativeDateFormat org.ocpsoft.prettytime.PrettyTime
Ruby
命名
为了与 Intl.NumberFormat 和 Intl.DateTimeFormat 保持一致,我们为这个新特性选择了类似的形式。创建 Intl.RelativeTimeFormat 实例是一个昂贵的操作,需要解析区域设置数据,而且很可能,库会尝试缓存这些实例,就像他们对 Intl.NumberFormat 和 Intl.DateTimeFormat 所做的那样。
我们还选择了 style 作为在不同格式化形式之间切换的主要方式,以与 Intl.NumberFormat 和 Intl.DateTimeFormat 保持一致。
由于这个新特性确实格式化提供的值,就像 Intl.NumberFormat 和 Intl.DateTimeFormat 的实例一样,我们选择了相同的形式,通过提供实例的 format(value) 方法,该方法返回格式化后的字符串值。
输入采用数字而不是日期对象
相对时间用于显示日期距离,因此输入的自然形式应该直观地是一个日期对象。但是,在此 API 中,我们选择接受数字而不是日期对象,原因如下:
- 基本上,将数字作为格式方法的输入而不是日期对象,大大简化了此提案的范围,同时仍然完全解决了主要目标,即提供解决此问题领域的 i18n 构建块。
- 接受日期对象意味着我们应该实现比较逻辑(相对时间是关于目标日期和源日期之间的日期距离)。源日期通常是 现在,但并不总是。我们必须解决修改它的问题。请参阅 #4。
- 接受日期对象还意味着我们应该允许不同的日历计算,这暗示
Date应该支持它。请参阅 #6 和 #13。 - 接受日期对象表明我们应该能够实现 bestFit 算法,这在标准化适用于所有情况的方法方面有其自身的 API 挑战。请参阅 #7、#14 和 #15。我们可能需要为用户提供一个标志,没有默认设置,以在日历计算的选项之间进行选择。
接受数字作为输入而不是暴露底层数据库
在“可扩展 Web”的背景下,有人提出一个想法:仅暴露引擎的 CLDR 数据库副本,而不是提供更高级别的接口会更好。对于本规范,已经有一个 JS 对象模型准备好了——区域设置数据库在规范内部表示为 JavaScript 对象。
但是,我们选择不采用这种方式,原因如下:
- 如上所述,该 API 已经相当低级,接受数字而不是日期。
- 尽管对于将日期舍入到单位的策略有不同的用例,但我们还没有遇到需要查看底层数据的用例。
- 这个新 API 与之前的 API 类似,这对学习该系统的人应该是有用的。
- CLDR 会随时间改变模式;如果数据模型改进,实现可以透明地升级用户,通过相同的 API 获得更好的结果。但是,如果我们冻结在当前逻辑,旧的数据模型将需要被模拟。
与 UnitFormat 的区别
RelativeTimeFormat 和 UnitFormat 之间的根本区别在于,RelativeTimeFormat 显示相对单位(例如,5 days ago 或 in 5 days),而 UnitFormat 显示绝对单位(例如,-5 meters 或 5 meters)。请注意,RelativeTimeFormat 根据值符号方向使用不同的国际化消息,而 UnitFormat 对所有值使用相同的国际化消息。
倒计时,例如,15 天 0 小时 27 分钟 52 秒
例如,倒计时是 UnitFormat 和 ListFormat 的混合体,而不是 RelativeTimeFormat。
NumberFormat 选项(例如,useGrouping、maximumFractionDigits)
RelativeTimeFormat 消息可能包含数字部分(例如,1,000 days ago 中的 1,000),这些部分使用 NumberFormat 默认选项进行格式化。
在此设计中,我们没有发现任何用例可以证明允许更改/覆盖这些 NumberFormat 默认选项是合理的。因此,RelativeTimeFormat 不包含任何 NumberFormat 选项。
API
Intl.RelativeTimeFormat([locales[, options]])
Intl.RelativeTimeFormat 对象是一个构造函数,用于创建能够进行语言敏感的相对时间格式化的对象。
locales
可选。一个包含 BCP 47 语言标签的字符串,或此类字符串的数组。有关 locales 参数的一般形式和解释,请参阅 Intl 页面。
options
可选。一个包含以下部分或全部属性的对象:
localeMatcher
要使用的区域设置匹配算法。可能的值为 "lookup" 和 "best fit";默认值为 "best fit"。有关此选项的信息,请参阅 Intl 页面。
numeric
输出消息的格式。可能的值为 "always"(默认值,例如,1 day ago)或 "auto"(例如,yesterday)。"auto" 允许输出中不必总是使用数值。
style
国际化消息的长度。可能的值为:"long"(默认值,例如,in 1 month);"short"(例如,in 1 mo.)或 "narrow"(例如,in 1 mo.)。对于某些区域设置,narrow 样式可能类似于 short 样式。
示例
Intl.RelativeTimeFormat.prototype.format(value, unit)
Intl.RelativeTimeFormat.prototype.format 方法根据此 Intl.RelativeTimeFormat 对象的区域设置和格式化选项格式化 value 和 unit。
虽然此方法自动提供正确的复数形式,但语法形式在其他方面尽可能中性。由调用者负责处理截断逻辑,例如决定显示“in 7 days”还是“in 1 week”。此 API 不支持涉及复合单位的相对日期。例如“in 5 days and 4 hours”。
value
用于国际化相对时间消息的数值。
unit
用于相对时间国际化消息的单位。可能的值为:"year"、"quarter"、"month"、"week"、"day"、"hour"、"minute"、"second"。也允许复数形式。
示例
此外,通过组合类选项 style 和 unit,您可以实现以下任何结果:
Intl.RelativeTimeFormat.prototype.formatToParts(value, unit)
Intl.RelativeTimeFormat.prototype.formatToParts 方法是 format 方法的一个版本,它返回一个对象数组,这些对象表示对象的“部分”,将格式化的数字分隔为其组成部分,并将其与周围的其他文本分开。这些对象有两个属性:type,一个 NumberFormat formatToParts 类型,以及 value,它是输出的字符串组件。如果“部分”来自 NumberFormat,它将有一个 unit 属性,表示正在格式化的单位;作为更大框架一部分的文本将不具有此属性。