For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/year/2025/proposal-intl-duration-format.md.
  • 简体中文
  • Intl.DurationFormat S4

    中文标题:Intl.DurationFormat 提案

    提案概览
    提案速览

    该提案引入了 Intl.DurationFormat,这是一个新的 Intl API,用于对时间持续时间进行区域设置感知的格式化。它支持多个持续时间单位、格式化宽度(长、短、窄、数字)、按单位的样式/显示选项以及亚秒小数的显示。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    Intl.DurationFormat 提案

    阶段: 4

    提案负责人: Younies Mahmoud, Ujjwal Sharma

    作者: Younies Mahmoud, Ujjwal Sharma

    阶段 3 审阅者

    资源

    状态

    • 该提案在 2020 年 2 月的 TC39 会议上达到阶段 1。
    • 该提案在 2020 年 6 月的 TC39 会议上达到阶段 2。
    • 该提案在 2021 年 10 月的 TC39 会议上达到阶段 3。
    • 该提案在 2024 年 12 月的 TC39 会议上达到阶段 4。

    概述

    • 时间持续时间是指某事从开始到结束持续多长时间。它可以由单个时间单位或多个时间单位表示。
      • 例如,
        • 10000 秒
        • 2 小时 46 分钟 40 秒
    • 每个地区都有自己的持续时间格式化方式。
      • 例如:
        • en-US: 1 hour, 46 minutes and 40 seconds
        • fr-FR: 1 heure, 46 minutes et 40 secondes
    • 时间持续时间有多种宽度。
      • 例如,宽和短
        • 1 hour, 46 minutes and 40 seconds → 宽
        • 1 hr, 46 min, 40 sec → 短

    快速开始

    new Intl.DurationFormat("fr-FR", { style: "long" }).format({
        hours: 1,
        minutes: 46,
        seconds: 40,
    });
    // => "1 heure, 46 minutes et 40 secondes"

    动机

    • 用户需要根据其应用程序的要求来进行各种类型的持续时间格式化。例如,要显示航班飞行时间,持续时间应为短格式或窄格式
      • "1 hr 40 min 60 sec" → 短
      • "1h 40m 60s" → 窄

    需求与设计

    在本节中,我们将说明每个用户需求以及每个需求的设计

    支持的持续时间单位

    • 用户需要以下字段支持
      • 小时
      • 分钟
      • 毫秒
      • 微秒
      • 纳秒
    设计
    • 持续时间对象支持与 Temporal.Duration 相同的字段,其中包含:
      • years
      • months
      • weeks
      • days
      • hours
      • minutes
      • seconds
      • milliseconds
      • microseconds
      • nanoseconds

    输入值

    • 用户需要确定如何输入持续时间值。例如,如果用户需要格式化 1000 秒 ,用户如何将值传递给格式化函数。
    设计
    • 输入值将是一个持续时间对象,包含某些受支持的持续时间单位字段的数字。
    • 示例:new DurationFormat().format({hours: 3, minutes: 4});

    格式化宽度

    用户希望确定以下几种格式化宽度

    格式化宽度示例
    1 hour and 50 minutes
    1 hr, 50 min
    1h 50m
    数字1:50:00
    设计
    • 用户可以使用参数 style 确定格式化宽度,该参数的值可以是以下字符串之一:
      • "long"
      • "short"
      • "narrow"
      • "digital"
    • 每个字段的宽度可以在选项中单独设置,例如:{ years: "long", months: "short", days: "narrow" }

    确定持续时间单位

    DurationFormat 不会对输入进行任何算术运算或舍入。 相反,用户必须修改输入以确保输入在所需范围内。

    为避免意外遗漏持续时间的一部分,DurationFormat 始终输出所有非零字段(除了由 fractionalDigits 截断的亚秒字段)。 希望省略非零字段的调用者(例如,仅显示持续时间的日期或时间部分)应编辑输入持续时间。

    设计
    • 持续时间存储在包含上述字段的持续时间对象中。
    • 示例:
        const duration = { hours: 1, minutes: 2, seconds: 33 };

    隐藏零值字段

    在大多数情况下,用户希望避免显示零值字段。默认情况下,所有零值字段都被隐藏。如果您为特定字段指定了样式,则它总是被显示,但您可以通过将该特定字段的显示选项显式设置为 "auto" 来覆盖该行为。

    设计

    对于每个字段 foo,都有一个选项 fooDisplay,默认设置为 "auto"。将该选项设置为 "always" 会导致该字段即使为零也会被显示;例如,要始终显示 "day" 字段,设置 { dayDisplay: "always" }。如果您通过设置 foo 选项来指定该字段的样式,则 fooDisplay 的默认值变为 "always";例如,{ day: "short" } 暗示 { day: "short", dayDisplay: "always" }

    感知区域设置的格式

    • 用户需要格式依赖于区域设置
    • 例如:
      • en-US
        • 1 hour, 46 minutes and 40 seconds
      • fr-FR
        • 1 heure, 46 minutes et 40 secondes
    设计

    将区域设置作为字符串格式的第一个参数,或将区域设置的排序列表指定为字符串数组。

    显示小数值

    有时希望将最小的亚秒单位不单独显示,而是作为紧邻的较大单位的分数显示。

    设计

    我们允许用户指定一个 fractionalDigits 选项,该选项将显示设置为 "auto" 的最小亚秒单位,如果非零且这些值的样式设置为 "numeric",则作为前一个单位的分数显示。使用的位数将是传递给此选项的值。默认情况下,fractionalDigits 是未定义的。在这种情况下,将包含恰好显示整个持续时间所需的尽可能多的小数位。如果需要舍入,我们向零舍入。

    示例
    
    const duration = { seconds: 12, milliseconds: 345, microseconds: 600 } ;
    
    new Intl.DurationFormat('en', { style: "digital", fractionalDigits: 2 }).format(duration); 
    // "0:00:12.35"
    
    new Intl.DurationFormat('en', { seconds: "numeric", fractionalDigits: 2 }).format(duration); 
    // "12.35"
    
    > new Intl.DurationFormat('en', { seconds: "numeric", fractionalDigits: 5 }).format(duration); 
    // "12.34560"
    
    > new Intl.DurationFormat('en', { seconds: "numeric"}).format(duration); 
    // "12.3456"
    

    API 设计

    构造函数

    语法
    new Intl.DurationFormat(locales, options)
    参数
    • locales: Array<string> | string: 区域设置字符串或按偏好递减顺序排列的区域设置字符串列表。
    • options?: object: 用于配置实例行为的对象。它可能具有以下部分或全部属性:
      • localeMatcher: "best fit" | "lookup": 表示使用哪种区域设置匹配算法的字符串。默认为 "best fit"
      • numberingSystem: string: 包含用于数字格式化的编号系统名称的字符串。
      • style: "long" | "short" | "narrow" | "digital": 用于格式化的基础样式。可以通过设置更细粒度的选项按单位覆盖。默认为 "short"
      • years: "long" | "short" | "narrow": 用于格式化年的样式。
      • yearsDisplay: "always" | "auto": 是否始终显示年,或仅非零时显示。
      • months: "long" | "short" | "narrow": 用于格式化月的样式。
      • monthsDisplay: "always" | "auto": 是否始终显示月,或仅非零时显示。
      • weeks: "long" | "short" | "narrow": 用于格式化周的样式。
      • weeksDisplay: "always" | "auto": 是否始终显示周,或仅非零时显示。
      • days: "long" | "short" | "narrow": 用于格式化日的样式。
      • daysDisplay: "always" | "auto": 是否始终显示日,或仅非零时显示。
      • hours: "long" | "short" | "narrow" | "numeric" | "2-digit": 用于格式化小时的样式。
      • hoursDisplay: "always" | "auto": 是否始终显示小时,或仅非零时显示。
      • minutes: "long" | "short" | "narrow" | "numeric" | "2-digit": 用于格式化分钟的样式。
      • minutesDisplay: "always" | "auto": 是否始终显示分钟,或仅非零时显示。
      • seconds: "long" | "short" | "narrow" | "numeric" | "2-digit": 用于格式化秒的样式。
      • secondsDisplay: "always" | "auto": 是否始终显示秒,或仅非零时显示。
      • milliseconds: "long" | "short" | "narrow" | "numeric": 用于格式化毫秒的样式。
      • millisecondsDisplay: "always" | "auto": 是否始终显示毫秒,或仅非零时显示。
      • microseconds: "long" | "short" | "narrow" | "numeric": 用于格式化微秒的样式。
      • microsecondsDisplay: "always" | "auto": 是否始终显示微秒,或仅非零时显示。
      • nanoseconds: "long" | "short" | "narrow" | "numeric": 用于格式化纳秒的样式。
      • nanosecondsDisplay: "always" | "auto": 是否始终显示纳秒,或仅非零时显示。
      • fractionalDigits: number: 输出中显示的小数位数。 额外的小数位将被向零截断。 (Temporal.Duration.prototype.round 可用于获得不同的舍入行为。) 通常此选项适用于小数秒,但实际上此选项适用于使用 "numeric""2-digit" 样式的最大秒或更小单位。 例如,如果选项是 { seconds: "narrow", milliseconds: "numeric", fractionalDigits: 4},则输出为 "12.3456 seconds"。 如果省略此选项,则仅显示非零小数,并省略尾随零。
    默认值
    • 对于除 "digital" 之外的所有样式,每个单位的样式选项默认为 style 的值;对于 "digital",年到日的单位默认为 "short",小时到纳秒的单位默认为 "numeric"
    • 如果 styleundefined,则所有值默认为 "short"
    • 如果相应的样式选项为 undefined,则每个单位的显示选项默认为 "auto",否则默认为 "always"
    注意
    • 某些区域设置可能在 "long""short" 之间或 "narrow""short" 之间共享相同的表示。 其他可能使用不同的表示,例如 "3 seconds"、"3 secs"、"3s"。
    • 任何样式为 "numeric" 的单位,如果前面有样式为 "numeric""2-digit" 的单位,则其行为应如同使用了 "2-digit" 样式。 例如,{hours: 'numeric', minutes: 'numeric'} 可以产生类似 "3:08" 的输出。

    Intl.DurationFormat#format

    语法
    new Intl.DurationFormat('en').format(duration)
    参数
    • duration (Temporal.Duration | string | object): 要格式化的持续时间。这可以是 Temporal.Duration 对象,也可以是可转换为一个的字符串或选项袋。
    返回值

    一个包含格式化持续时间的 string

    Intl.DurationFormat#formatToParts

    语法
    new Intl.DurationFormat('en').formatToParts(duration)
    参数
    • duration (Temporal.Duration | string | object): 要格式化的持续时间。这可以是 Temporal.Duration 对象,也可以是可转换为一个的字符串或选项袋。
    返回值

    一个包含格式化持续时间各部分的 Array<{type: string, value: string}>

    实现状态

    V8 原型

    制作了三个 v8 原型(尝试使用两个不同的可能 ICU 类),所有这些都是:

    1. 基于 icu::MeasureFormat::formatMeasures()
    2. 基于 LocalizedNumberFormatter 中对 "-and-" 单位的支持
    3. 基于 icu::ListFormatter 和 icu::number::LocalizedNumberFormatter,不依赖于 "X-and-Y" 单位。