├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .npmrc ├── LICENSE ├── README.md ├── index.html ├── package.json └── spec.emu /.gitattributes: -------------------------------------------------------------------------------- 1 | index.html -diff merge=ours 2 | spec.js -diff merge=ours 3 | spec.css -diff merge=ours 4 | index.html linguist-generated=true 5 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Deploy spec 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v1 12 | with: 13 | node-version: '12.x' 14 | - run: npm install 15 | - run: npm run build 16 | - name: commit changes 17 | uses: elstudio/actions-js-build/commit@v3 18 | with: 19 | commitMessage: "fixup: [spec] `npm run build`" 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Only apps should have lockfiles 40 | yarn.lock 41 | package-lock.json 42 | npm-shrinkwrap.json 43 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 ECMA TC39 and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proposal for Intl.DurationFormat 2 | 3 | **Stage**: 4 4 | 5 | **Champion**: [Younies Mahmoud](https://github.com/younies), [Ujjwal Sharma](https://github.com/ryzokuken) 6 | 7 | **Authors**: [Younies Mahmoud](https://github.com/younies), [Ujjwal Sharma](https://github.com/ryzokuken) 8 | 9 | **Stage 3 Reviewers** 10 | - Michael Ficarra [@michaelficarra](https://github.com/michaelficarra) 11 | - Ron Buckton [@rbuckton](https://github.com/rbuckton) 12 | - Ross Kirsling [@rkirsling](https://github.com/rkirsling) 13 | 14 | **Resources** 15 | - Spec text in [ecmarkup output format](https://tc39.es/proposal-intl-duration-format/) 16 | - [Stage 2 slides](https://docs.google.com/presentation/d/1QmrhwsYwlsfe8FJqgGarCIAySWxeZzDqCrVN3-DWiGk/edit?usp=sharing) 17 | - [Stage 3 slides](https://ryzokuken.dev/slides/2021-10-df#/) 18 | - [Polyfill from formatjs](https://formatjs.io/docs/polyfills/intl-durationformat) 19 | 20 | 21 | ## Status 22 | 23 | - This proposal reached Stage 1 at the 2020 Feb TC39 meeting. 24 | - This proposal reached Stage 2 at the 2020 June TC39 meeting. 25 | - This proposal reached Stage 3 at the 2021 October TC39 meeting. 26 | - This proposal reached Stage 4 at the 2024 December TC39 meeting. 27 | 28 | ## Overview 29 | 30 | * Time Duration is how long something lasts, from the start to end. It can be represented by a single time unit or multiple ones. 31 | + For example, 32 | - 10000 seconds 33 | - 2 hours 46 minutes 40 seconds 34 | * Every locale has its own way to format duration. 35 | + For example: 36 | - en-US: 1 hour, 46 minutes and 40 seconds 37 | - fr-FR: 1 heure, 46 minutes et 40 secondes 38 | * There are multiple widths for the time duration. 39 | + For example, wide and short 40 | - 1 hour, 46 minutes and 40 seconds → Wide 41 | - 1 hr, 46 min, 40 sec → Short 42 | 43 | ## Quick Start 44 | 45 | ```javascript 46 | new Intl.DurationFormat("fr-FR", { style: "long" }).format({ 47 | hours: 1, 48 | minutes: 46, 49 | seconds: 40, 50 | }); 51 | // => "1 heure, 46 minutes et 40 secondes" 52 | ``` 53 | 54 | ## Motivation 55 | 56 | * Users need all types of duration formatting depending on the requirements of their application. For example, to show how long a flight takes, the duration should be in Short or Narrow format 57 | + "1 hr 40 min 60 sec" → Short 58 | + "1h 40m 60s" → Narrow 59 | 60 | ## Requirements & Design 61 | 62 | In this section, we are going to illustrate each user needs (requirements) and a design for each need (requirement) 63 | 64 | ### Supported Duration Units 65 | 66 | * Users need the following fields to be supported 67 | + Years 68 | + Months 69 | + Weeks 70 | + Days 71 | + Hours 72 | + Minutes 73 | + Seconds 74 | + Milliseconds 75 | + Microseconds 76 | + Nanoseconds 77 | 78 | #### Design 79 | 80 | * Duration objects support the same fields as in [ `Temporal.Duration` ](https://github.com/tc39/proposal-temporal/blob/main/docs/duration.md), which contains: 81 | + years 82 | + months 83 | + weeks 84 | + days 85 | + hours 86 | + minutes 87 | + seconds 88 | + milliseconds 89 | + microseconds 90 | + nanoseconds 91 | 92 | ### Input Value 93 | 94 | + Users need to identify how to input a duration value. For example, if a user needs to format `1000 seconds` , how could the user pass the value to the formatting function. 95 | 96 | #### Design 97 | 98 | * Input value will be a duration object, containing fields for some number of the supported duration units fields. 99 | * Example: `new DurationFormat().format({hours: 3, minutes: 4});` 100 | 101 | ### Formatting width 102 | 103 | Users want to determine several types of the formatting width as following 104 | 105 | | Format width | Example | 106 | |--------------|-----------------------| 107 | | Long | 1 hour and 50 minutes | 108 | | Short | 1 hr, 50 min | 109 | | Narrow | 1h 50m | 110 | | Digital | 1:50:00 | 111 | 112 | #### Design 113 | 114 | + The user can determine the formatting width using a parameter `style` and the value of this parameter may be one of the following strings: 115 | - `"long"` 116 | - `"short"` 117 | - `"narrow"` 118 | - `"digital"` 119 | + The width of each field can be set separately in the options, for example: `{ years: "long", months: "short", days: "narrow" }`. 120 | 121 | ### Determining Duration Units 122 | 123 | `DurationFormat` does not do any arithmetic operations nor rounding on the input implicitly. 124 | Instead, the user must edit the input to ensure the input is within the desired range. 125 | 126 | To avoid accidentally omitting part of the duration, `DurationFormat` always outputs all nonzero fields (except sub-second fields truncated by `fractionalDigits`). 127 | Callers who want to omit nonzero fields (for example, only showing the date or time portion of the duration) should edit the input duration. 128 | 129 | #### Design 130 | 131 | * Durations are stored in duration objects containing the fields above. 132 | * Example: 133 | 134 | ``` javascript 135 | const duration = { hours: 1, minutes: 2, seconds: 33 }; 136 | ``` 137 | 138 | ### Hide zero-value fields 139 | 140 | In most cases, users want to avoid displaying zero-value fields. All zero-valued fields are hidden by default. If you specify the style for a specific field, then it is always displayed, but you can override that behavior by also setting the display option for that particular field to `"auto"` again explicitly. 141 | 142 | #### Design 143 | 144 | For each field `foo`, there is an option `fooDisplay` that is set to `"auto"` by default. Setting that option to `"always"` causes that field to be displayed even if it is zero; for example, to always show the "day" field, set `{ dayDisplay: "always" }`. If you specify the style for that field by setting the `foo` option, then the default for `fooDisplay` becomes `"always"`; for example, `{ day: "short" }` implies `{ day: "short", dayDisplay: "always" }`. 145 | 146 | ### Locale-aware format 147 | 148 | * Users needs the formatting to be dependent on the locale 149 | * For example: 150 | + en-US 151 | - 1 hour, 46 minutes and 40 seconds 152 | + fr-FR 153 | - 1 heure, 46 minutes et 40 secondes 154 | 155 | #### Design 156 | 157 | Adding the locale in string format as a first argument, or specifying a ranked list of locales as an array of string values. 158 | 159 | ### Display fractional values 160 | 161 | Sometimes it is desirable to display the smallest sub-second unit not by itself but as a fraction of the immediately larger unit. 162 | 163 | #### Design 164 | 165 | We allow users to specify a `fractionalDigits` option that will display the smallest sub-second unit with display set to `"auto"` as a fraction of the previous unit if it is non-zero and if these values have style set to `"numeric"`. The number of digits used will be the value passed to this option. By default `fractionalDigits` is undefined. In this case, exactly as many fractional digits as needed to display the whole duration are included. If rounding is necessary, we round toward 0. 166 | 167 | #### Example 168 | 169 | ```javascript 170 | 171 | const duration = { seconds: 12, milliseconds: 345, microseconds: 600 } ; 172 | 173 | new Intl.DurationFormat('en', { style: "digital", fractionalDigits: 2 }).format(duration); 174 | // "0:00:12.35" 175 | 176 | new Intl.DurationFormat('en', { seconds: "numeric", fractionalDigits: 2 }).format(duration); 177 | // "12.35" 178 | 179 | > new Intl.DurationFormat('en', { seconds: "numeric", fractionalDigits: 5 }).format(duration); 180 | // "12.34560" 181 | 182 | > new Intl.DurationFormat('en', { seconds: "numeric"}).format(duration); 183 | // "12.3456" 184 | 185 | ``` 186 | 187 | ## API design 188 | 189 | ### Constructor 190 | 191 | #### Syntax 192 | 193 | ```javascript 194 | new Intl.DurationFormat(locales, options) 195 | ``` 196 | 197 | #### Parameters 198 | 199 | * `locales: Array | string`: A locale string or a list of locale strings in decreasing order of preference. 200 | * `options?: object`: An object for configuring the behavior of the instance. It may have some or all of the following properties: 201 | * `localeMatcher: "best fit" | "lookup"`: A string denoting which locale matching algorithm to use. Defaults to `"best fit"`. 202 | * `numberingSystem: string`: A string containing the name of the numbering system to be used for number formatting. 203 | * `style: "long" | "short" | "narrow" | "digital"`: The base style to be used for formatting. This can be overriden per-unit by setting the more granular options. Defaults to `"short"`. 204 | * `years: "long" | "short" | "narrow"`: The style to be used for formatting years. 205 | * `yearsDisplay: "always" | "auto"`: Whether to always display years, or only if nonzero. 206 | * `months: "long" | "short" | "narrow"`: The style to be used for formatting months. 207 | * `monthsDisplay: "always" | "auto"`: Whether to always display months, or only if nonzero. 208 | * `weeks: "long" | "short" | "narrow"`: The style to be used for formatting weeks. 209 | * `weeksDisplay: "always" | "auto"`: Whether to always display weeks, or only if nonzero. 210 | * `days: "long" | "short" | "narrow"`: The style to be used for formatting days. 211 | * `daysDisplay: "always" | "auto"`: Whether to always display days, or only if nonzero. 212 | * `hours: "long" | "short" | "narrow" | "numeric" | "2-digit"`: The style to be used for formatting hours. 213 | * `hoursDisplay: "always" | "auto"`: Whether to always display hours, or only if nonzero. 214 | * `minutes: "long" | "short" | "narrow" | "numeric" | "2-digit"`: The style to be used for formatting minutes. 215 | * `minutesDisplay: "always" | "auto"`: Whether to always display minutes, or only if nonzero. 216 | * `seconds: "long" | "short" | "narrow" | "numeric" | "2-digit"`: The style to be used for formatting seconds. 217 | * `secondsDisplay: "always" | "auto"`: Whether to always display seconds, or only if nonzero. 218 | * `milliseconds: "long" | "short" | "narrow" | "numeric"`: The style to be used for formatting milliseconds. 219 | * `millisecondsDisplay: "always" | "auto"`: Whether to always display milliseconds, or only if nonzero. 220 | * `microseconds: "long" | "short" | "narrow" | "numeric"`: The style to be used for formatting microseconds. 221 | * `microsecondsDisplay: "always" | "auto"`: Whether to always display microseconds, or only if nonzero. 222 | * `nanoseconds: "long" | "short" | "narrow" | "numeric"`: The style to be used for formatting nanoseconds. 223 | * `nanosecondsDisplay: "always" | "auto"`: Whether to always display nanoseconds, or only if nonzero. 224 | * `fractionalDigits: number`: How many fractional digits to display in the output. 225 | Additional decimal places will be truncated towards zero. 226 | (`Temporal.Duration.prototype.round` can be used to obtain different rounding behavior.) 227 | Normally this option applies to fractional seconds, but this option actually applies to the largest seconds-or-smaller unit that uses the `"numeric"` or `"2-digit"` style. 228 | For example, if options are `{ seconds: "narrow", milliseconds: "numeric", fractionalDigits: 4}` then the output is "12.3456 seconds". 229 | If this option is omitted, only nonzero decimals will be displayed and trailing zeroes will be omitted. 230 | 231 | ##### Default values 232 | 233 | * The per-unit style options default to the value of `style` for all styles except `"digital"`, for which units years till days default to `"short"` and hours till nanoseconds default to `"numeric"`. 234 | * If `style` is `undefined`, all values default to `"short"` 235 | * The per-unit display options default to `"auto"` if the corresponding style option is `undefined` and `"always"` otherwise. 236 | 237 | #### Notes 238 | 239 | * Some locales may share the same representation between `"long"` and `"short"` or between `"narrow"` and `"short"`. Others may use different representations for each one, e.g. "3 seconds", "3 secs", "3s". 240 | * Any unit with the style `"numeric"` preceded by a unit of style `"numeric"` or `"2-digit"` should act like the style `"2-digit"` was used instead. For example, `{hours: 'numeric', minutes: 'numeric'}` can produce output like "3:08". 241 | 242 | ### `Intl.DurationFormat#format` 243 | 244 | #### Syntax 245 | 246 | ```javascript 247 | new Intl.DurationFormat('en').format(duration) 248 | ``` 249 | 250 | #### Parameters 251 | 252 | * `duration` (`Temporal.Duration` | `string` | `object`): The duration to be formatted. This could either be a `Temporal.Duration` object or a string or options bag that can be converted into one. 253 | 254 | #### Returns 255 | 256 | A `string` containing the formatted duration. 257 | 258 | ### `Intl.DurationFormat#formatToParts` 259 | 260 | #### Syntax 261 | 262 | ```javascript 263 | new Intl.DurationFormat('en').formatToParts(duration) 264 | ``` 265 | 266 | #### Parameters 267 | 268 | * `duration` (`Temporal.Duration` | `string` | `object`): The duration to be formatted. This could either be a `Temporal.Duration` object or a string or options bag that can be converted into one. 269 | 270 | #### Returns 271 | 272 | An `Array<{type: string, value: string}>` containing the formatted duration in parts. 273 | 274 | ## Implementation Status 275 | 276 | ### V8 Prototypes 277 | Three v8 prototypes (try to use two different possible ICU classes) were made, ALL are: 278 | * Sync with ["Stage 1 Draft / June 1, 2020" version of spec](https://github.com/tc39/proposal-intl-duration-format/commit/fc8ff131cf7e688810b38d7e95d6fa44b1f1964e) 279 | * Flag --harmony_intl_duration_format 280 | * Have not implement any changes not yet spec out in https://tc39.es/proposal-intl-duration-format/ such as 281 | + hideZeroValued 282 | + smallestUnit / largestUnit 283 | 284 | 1. Base the implementation on [icu::MeasureFormat::formatMeasures()](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/classicu_1_1MeasureFormat.html#ade104d40578223bd194050914b090904) 285 | * https://chromium-review.googlesource.com/c/v8/v8/+/2762664 286 | * Not yet implment formatToParts 287 | * Need solution of [ICU-21543 "Add methods to return FormattedValue to MeasureFormat "](https://unicode-org.atlassian.net/browse/ICU-21543) to implement formatToParts(). 288 | 2. Based on [the support of "-and-" unit in LocalizedNumberFormatter](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/classicu_1_1number_1_1LocalizedNumberFormatter.html) 289 | * https://chromium-review.googlesource.com/c/v8/v8/+/2775300 290 | * Not yet implment formatToParts 291 | * Not yet implement style:"digital" 292 | * Need solution of the following to implement formatToParts(): 293 | + [ICU-21544 "unit format in number formatter return U_INTERNAL_PROGRAM_ERROR with "year-and-" (except month) and "month-and-""](https://unicode-org.atlassian.net/browse/ICU-21544) 294 | + [ICU-21547 "nextPosition() of FormattedNumber of unit with "-and-" is buggy"](https://unicode-org.atlassian.net/browse/ICU-21547) 295 | 3. Based on icu::ListFormatter and icu::number::LocalizedNumberFormatter w/o depend on the "X-and-Y" units. 296 | * https://chromium-review.googlesource.com/c/v8/v8/+/2776518 297 | * Implements formatToParts 298 | * Not yet implement style:"digital" 299 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "proposal-intl-duration-format", 4 | "description": "Proposal for Intl.DurationFormat", 5 | "scripts": { 6 | "start": "npm run build-loose -- --watch", 7 | "build": "npm run build-loose -- --strict", 8 | "build-loose": "ecmarkup --verbose --lint-spec --load-biblio @tc39/ecma262-biblio --load-biblio @tc39/ecma402-biblio spec.emu index.html" 9 | }, 10 | "homepage": "https://tc39.es/proposal-intl-duration-format/", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/tc39/proposal-intl-duration-format.git" 14 | }, 15 | "license": "MIT", 16 | "devDependencies": { 17 | "@tc39/ecma262-biblio": "=2.1.2799", 18 | "@tc39/ecma402-biblio": "=2.1.1122", 19 | "ecmarkup": "^20.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /spec.emu: -------------------------------------------------------------------------------- 1 | 2 | 3 |
   4 | title: Intl.DurationFormat
   5 | stage: 3
   6 | location: https://tc39.es/proposal-intl-duration-format/
   7 | contributors: Ujjwal Sharma, Younies Mahmoud
   8 | 
9 | 10 |

DurationFormat Objects

11 | 12 | 13 |

Abstract Operations for DurationFormat Objects

14 | 15 | 16 |

Duration Records

17 |

A Duration Record is a Record value used to represent a Duration.

18 |

Duration Records have the fields listed in

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 54 | 55 | 56 | 57 | 60 | 61 | 62 | 63 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 | 78 | 79 | 80 | 81 | 84 | 85 |
FieldMeaning
[[Years]] 28 | The number of years in the duration. 29 |
[[Months]] 34 | The number of months in the duration. 35 |
[[Weeks]] 40 | The number of weeks in the duration. 41 |
[[Days]] 46 | The number of days in the duration. 47 |
[[Hours]] 52 | The number of hours in the duration. 53 |
[[Minutes]] 58 | The number of minutes in the duration. 59 |
[[Seconds]] 64 | The number of seconds in the duration. 65 |
[[Milliseconds]] 70 | The number of milliseconds in the duration. 71 |
[[Microseconds]] 76 | The number of microseconds in the duration. 77 |
[[Nanoseconds]] 82 | The number of nanoseconds in the duration. 83 |
86 |
87 |
88 | 89 | 90 |

91 | ToIntegerIfIntegral ( 92 | _argument_: an ECMAScript language value, 93 | ): either a normal completion containing an integer, or an abrupt completion 94 |

95 |
96 |
description
97 |
It converts _argument_ to an integer representing its Number value, or throws a *RangeError* when that value is not integral.
98 |
99 | 100 | 1. Let _number_ be ? ToNumber(_argument_). 101 | 1. If _number_ is not an integral Number, throw a *RangeError* exception. 102 | 1. Return ℝ(_number_). 103 | 104 |
105 | 106 | 107 |

108 | ToDurationRecord ( 109 | _input_: an ECMAScript language value 110 | ): either a normal completion containing a Duration Record, or an abrupt completion 111 |

112 |
113 |
description
114 |
It converts a given object that represents a Duration into a Duration Record.
115 |
116 | 117 | 118 | 1. If _input_ is not an Object, then 119 | 1. If _input_ is a String, throw a *RangeError* exception. 120 | 1. Throw a *TypeError* exception. 121 | 1. Let _result_ be a new Duration Record with each field set to 0. 122 | 1. Let _days_ be ? Get(_input_, *"days"*). 123 | 1. If _days_ is not *undefined*, set _result_.[[Days]] to ? ToIntegerIfIntegral(_days_). 124 | 1. Let _hours_ be ? Get(_input_, *"hours"*). 125 | 1. If _hours_ is not *undefined*, set _result_.[[Hours]] to ? ToIntegerIfIntegral(_hours_). 126 | 1. Let _microseconds_ be ? Get(_input_, *"microseconds"*). 127 | 1. If _microseconds_ is not *undefined*, set _result_.[[Microseconds]] to ? ToIntegerIfIntegral(_microseconds_). 128 | 1. Let _milliseconds_ be ? Get(_input_, *"milliseconds"*). 129 | 1. If _milliseconds_ is not *undefined*, set _result_.[[Milliseconds]] to ? ToIntegerIfIntegral(_milliseconds_). 130 | 1. Let _minutes_ be ? Get(_input_, *"minutes"*). 131 | 1. If _minutes_ is not *undefined*, set _result_.[[Minutes]] to ? ToIntegerIfIntegral(_minutes_). 132 | 1. Let _months_ be ? Get(_input_, *"months"*). 133 | 1. If _months_ is not *undefined*, set _result_.[[Months]] to ? ToIntegerIfIntegral(_months_). 134 | 1. Let _nanoseconds_ be ? Get(_input_, *"nanoseconds"*). 135 | 1. If _nanoseconds_ is not *undefined*, set _result_.[[Nanoseconds]] to ? ToIntegerIfIntegral(_nanoseconds_). 136 | 1. Let _seconds_ be ? Get(_input_, *"seconds"*). 137 | 1. If _seconds_ is not *undefined*, set _result_.[[Seconds]] to ? ToIntegerIfIntegral(_seconds_). 138 | 1. Let _weeks_ be ? Get(_input_, *"weeks"*). 139 | 1. If _weeks_ is not *undefined*, set _result_.[[Weeks]] to ? ToIntegerIfIntegral(_weeks_). 140 | 1. Let _years_ be ? Get(_input_, *"years"*). 141 | 1. If _years_ is not *undefined*, set _result_.[[Years]] to ? ToIntegerIfIntegral(_years_). 142 | 1. If _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, and _nanoseconds_ are all *undefined*, throw a *TypeError* exception. 143 | 1. If IsValidDuration( _result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]) is *false*, then 144 | 1. Throw a *RangeError* exception. 145 | 1. Return _result_. 146 | 147 |
148 | 149 | 150 |

151 | DurationSign ( 152 | _duration_: a Duration Record, 153 | ): -1, 0, or 1 154 |

155 |
156 |
description
157 |
It returns 1 if the most significant non-zero field in the _duration_ argument is positive, and -1 if the most significant non-zero field is negative. If all of _duration_'s fields are zero, it returns 0.
158 |
159 | 160 | 1. For each value _v_ of « _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]] », do 161 | 1. If _v_ < 0, return -1. 162 | 1. If _v_ > 0, return 1. 163 | 1. Return 0. 164 | 165 |
166 | 167 | 168 |

169 | IsValidDuration ( 170 | _years_: an integer, 171 | _months_: an integer, 172 | _weeks_: an integer, 173 | _days_: an integer, 174 | _hours_: an integer, 175 | _minutes_: an integer, 176 | _seconds_: an integer, 177 | _milliseconds_: an integer, 178 | _microseconds_: an integer, 179 | _nanoseconds_: an integer, 180 | ): a Boolean 181 |

182 |
183 |
description
184 |
It returns *true* if its arguments form valid input from which to construct a Duration Record, and *false* otherwise.
185 |
186 | 187 | 1. Let _sign_ be 0. 188 | 1. For each value _v_ of « _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ », do 189 | 1. If 𝔽(_v_) is not finite, return *false*. 190 | 1. If _v_ < 0, then 191 | 1. If _sign_ > 0, return *false*. 192 | 1. Set _sign_ to -1. 193 | 1. Else if _v_ > 0, then 194 | 1. If _sign_ < 0, return *false*. 195 | 1. Set _sign_ to 1. 196 | 1. If abs(_years_) ≥ 232, return *false*. 197 | 1. If abs(_months_) ≥ 232, return *false*. 198 | 1. If abs(_weeks_) ≥ 232, return *false*. 199 | 1. Let _normalizedSeconds_ be _days_ × 86,400 + _hours_ × 3600 + _minutes_ × 60 + _seconds_ + ℝ(𝔽(_milliseconds_)) × 10-3 + ℝ(𝔽(_microseconds_)) × 10-6 + ℝ(𝔽(_nanoseconds_)) × 10-9. 200 | 1. NOTE: The above step cannot be implemented directly using floating-point arithmetic. Multiplying by 10-3, 10-6, and 10-9 respectively may be imprecise when _milliseconds_, _microseconds_, or _nanoseconds_ is an unsafe integer. This multiplication can be implemented in C++ with an implementation of `std::remquo()` with sufficient bits in the quotient. String manipulation will also give an exact result, since the multiplication is by a power of 10. 201 | 1. If abs(_normalizedSeconds_) ≥ 253, return *false*. 202 | 1. Return *true*. 203 | 204 | The abstract operations ToIntegerIfIntegral, DurationSign, and IsValidDuration take the same parameters as the abstract operations of the same name in the Temporal proposal's specification, aside from the use of a Duration Record instead of a Temporal.Duration instance. They will be removed in favor of the equivalent Temporal abstract operations if the Temporal proposal becomes part of ECMAScript before this proposal does. 205 |
206 | 207 | 208 |

209 | GetDurationUnitOptions ( 210 | _unit_: a String, 211 | _options_: an Object, 212 | _baseStyle_: a String, 213 | _stylesList_: a List of Strings, 214 | _digitalBase_: a String, 215 | _prevStyle_: a String, 216 | _twoDigitHours_: a Boolean, 217 | ): either a normal completion containing a Record with [[Style]] and [[Display]] fields, or an abrupt completion 218 |

219 |
220 |
description
221 |
It extracts the relevant options for any given _unit_ from an Object and returns them as a Record.
222 |
223 | 224 | 225 | 1. Let _style_ be ? GetOption(_options_, _unit_, ~string~, _stylesList_, *undefined*). 226 | 1. Let _displayDefault_ be *"always"*. 227 | 1. If _style_ is *undefined*, then 228 | 1. If _baseStyle_ is *"digital"*, then 229 | 1. If _unit_ is not one of *"hours"*, *"minutes"*, or *"seconds"*, then 230 | 1. Set _displayDefault_ to *"auto"*. 231 | 1. Set _style_ to _digitalBase_. 232 | 1. Else, 233 | 1. If _prevStyle_ is *"fractional"*, *"numeric"* or *"2-digit"*, then 234 | 1. If _unit_ is not one of *"minutes"* or *"seconds"*, then 235 | 1. Set _displayDefault_ to *"auto"*. 236 | 1. Set _style_ to *"numeric"*. 237 | 1. Else, 238 | 1. Set _displayDefault_ to *"auto"*. 239 | 1. Set _style_ to _baseStyle_. 240 | 1. If _style_ is *"numeric"*, then 241 | 1. If _unit_ is one of *"milliseconds"*, *"microseconds"*, or *"nanoseconds"*, then 242 | 1. Set _style_ to *"fractional"*. 243 | 1. Set _displayDefault_ to *"auto"*. 244 | 1. Let _displayField_ be the string-concatenation of _unit_ and *"Display"*. 245 | 1. Let _display_ be ? GetOption(_options_, _displayField_, ~string~, « *"auto"*, *"always"* », _displayDefault_). 246 | 1. If _display_ is *"always"* and _style_ is *"fractional"*, then 247 | 1. Throw a *RangeError* exception. 248 | 1. If _prevStyle_ is *"fractional"*, then 249 | 1. If _style_ is not *"fractional"*, then 250 | 1. Throw a *RangeError* exception. 251 | 1. If _prevStyle_ is *"numeric"* or *"2-digit"*, then 252 | 1. If _style_ is not *"fractional"*, *"numeric"* or *"2-digit"*, then 253 | 1. Throw a *RangeError* exception. 254 | 1. If _unit_ is *"minutes"* or *"seconds"*, then 255 | 1. Set _style_ to *"2-digit"*. 256 | 1. If _unit_ is *"hours"* and _twoDigitHours_ is *true*, then 257 | 1. Set _style_ to *"2-digit"*. 258 | 1. Return the Record { 259 | [[Style]]: _style_, 260 | [[Display]]: _display_ 261 | }. 262 | 263 |
264 | 265 | 266 |

267 | ComputeFractionalDigits ( 268 | _durationFormat_: a DurationFormat Object, 269 | _duration_: a Duration Record, 270 | ): a mathematical value 271 |

272 |
273 |
description
274 |
It computes the sum of all values in _durationFormat_ units with *"fractional"* style, expressed as a fraction of the smallest unit of _durationFormat_ that does not use *"fractional"* style.
275 |
276 | 277 | 278 | 1. Let _result_ be 0. 279 | 1. Let _exponent_ be 3. 280 | 1. For each row of , except the header row, in table order, do 281 | 1. Let _style_ be the value of _durationFormat_'s internal slot whose name is the Style Slot value of the current row. 282 | 1. If _style_ is *"fractional"*, then 283 | 1. Assert: The Unit value of the current row is *"milliseconds"*, *"microseconds"*, or *"nanoseconds"*. 284 | 1. Let _value_ be the value of _duration_'s field whose name is the Value Field value of the current row. 285 | 1. Set _value_ to _value_ / 10_exponent_. 286 | 1. Set _result_ to _result_ + _value_. 287 | 1. Set _exponent_ to _exponent_ + 3. 288 | 1. Return _result_. 289 | 290 |
291 | 292 | 293 |

294 | NextUnitFractional ( 295 | _durationFormat_: a DurationFormat Object, 296 | _unit_: a String, 297 | ): a Boolean 298 |

299 |
300 |
description
301 |
It returns *true* if the next smallest unit uses the *"fractional"* style.
302 |
303 | 304 | 305 | 1. Assert: _unit_ is *"seconds"*, *"milliseconds"*, or *"microseconds"*. 306 | 1. If _unit_ is *"seconds"* and _durationFormat_.[[MillisecondsStyle]] is *"fractional"*, return *true*. 307 | 1. Else if _unit_ is *"milliseconds"* and _durationFormat_.[[MicrosecondsStyle]] is *"fractional"*, return *true*. 308 | 1. Else if _unit_ is *"microseconds"* and _durationFormat_.[[NanosecondsStyle]] is *"fractional"*, return *true*. 309 | 1. Return *false*. 310 | 311 |
312 | 313 | 314 |

315 | FormatNumericHours ( 316 | _durationFormat_: a DurationFormat object, 317 | _hoursValue_: an integer, 318 | _signDisplayed_: a Boolean, 319 | ) : a List of Records 320 |

321 |
322 |
description
323 |
_hoursValue_ is an integer indicating a number of hours. It creates the parts for _hoursValue_ according to the effective locale and the formatting options of _durationFormat_.
324 |
325 | 326 | 327 | 1. Let _result_ be a new empty List. 328 | 1. Let _hoursStyle_ be _durationFormat_.[[HoursStyle]]. 329 | 1. Assert: _hoursStyle_ is *"numeric"* or _hoursStyle_ is *"2-digit"*. 330 | 1. Let _nfOpts_ be OrdinaryObjectCreate(*null*). 331 | 1. Let _numberingSystem_ be _durationFormat_.[[NumberingSystem]]. 332 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"numberingSystem"*, _numberingSystem_). 333 | 1. If _hoursStyle_ is *"2-digit"*, then 334 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"minimumIntegerDigits"*, *2*𝔽). 335 | 1. If _signDisplayed_ is *false*, then 336 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"signDisplay"*, *"never"*). 337 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"useGrouping"*, *false*). 338 | 1. Let _nf_ be ! Construct(%Intl.NumberFormat%, « _durationFormat_.[[Locale]], _nfOpts_ »). 339 | 1. Let _hoursParts_ be PartitionNumberPattern(_nf_, _hoursValue_). 340 | 1. For each Record { [[Type]], [[Value]] } _part_ of _hoursParts_, do 341 | 1. Append the Record { [[Type]]: _part_.[[Type]], [[Value]]: _part_.[[Value]], [[Unit]]: *"hour"* } to _result_. 342 | 1. Return _result_. 343 | 344 |
345 | 346 | 347 |

348 | FormatNumericMinutes ( 349 | _durationFormat_: a DurationFormat Object, 350 | _minutesValue_: an integer, 351 | _hoursDisplayed_: a Boolean, 352 | _signDisplayed_: a Boolean, 353 | ) : a List of Records 354 |

355 |
356 |
description
357 |
_minutesValue_ is an integer indicating a number of minutes. It creates the parts for _minutesValue_ according to the effective locale and the formatting options of _durationFormat_.
358 |
359 | 360 | 361 | 1. Let _result_ be a new empty List. 362 | 1. If _hoursDisplayed_ is *true*, then 363 | 1. Let _separator_ be _durationFormat_.[[HourMinuteSeparator]]. 364 | 1. Append the Record { [[Type]]: *"literal"*, [[Value]]: _separator_, [[Unit]]: ~empty~ } to _result_. 365 | 1. Let _minutesStyle_ be _durationFormat_.[[MinutesStyle]]. 366 | 1. Assert: _minutesStyle_ is *"numeric"* or _minutesStyle_ is *"2-digit"*. 367 | 1. Let _nfOpts_ be OrdinaryObjectCreate(*null*). 368 | 1. Let _numberingSystem_ be _durationFormat_.[[NumberingSystem]]. 369 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"numberingSystem"*, _numberingSystem_). 370 | 1. If _minutesStyle_ is *"2-digit"*, then 371 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"minimumIntegerDigits"*, *2*𝔽). 372 | 1. If _signDisplayed_ is *false*, then 373 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"signDisplay"*, *"never"*). 374 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"useGrouping"*, *false*). 375 | 1. Let _nf_ be ! Construct(%Intl.NumberFormat%, « _durationFormat_.[[Locale]], _nfOpts_ »). 376 | 1. Let _minutesParts_ be PartitionNumberPattern(_nf_, _minutesValue_). 377 | 1. For each Record { [[Type]], [[Value]] } _part_ of _minutesParts_, do 378 | 1. Append the Record { [[Type]]: _part_.[[Type]], [[Value]]: _part_.[[Value]], [[Unit]]: *"minute"* } to _result_. 379 | 1. Return _result_. 380 | 381 |
382 | 383 | 384 |

385 | FormatNumericSeconds ( 386 | _durationFormat_: a DurationFormat Object, 387 | _secondsValue_: a mathematical value, 388 | _minutesDisplayed_ : a Boolean, 389 | _signDisplayed_: a Boolean, 390 | ) : a List of Records 391 |

392 |
393 |
description
394 |
_secondsValue_ is a mathematical value indicating a number of seconds. It creates the parts for _secondsValue_ according to the effective locale and the formatting options of _durationFormat_.
395 |
396 | 397 | 398 | 1. Let _result_ be a new empty List. 399 | 1. If _minutesDisplayed_ is *true*, then 400 | 1. Let _separator_ be _durationFormat_.[[MinuteSecondSeparator]]. 401 | 1. Append the Record { [[Type]]: *"literal"*, [[Value]]: _separator_, [[Unit]]: ~empty~ } to _result_. 402 | 1. Let _secondsStyle_ be _durationFormat_.[[SecondsStyle]]. 403 | 1. Assert: _secondsStyle_ is *"numeric"* or _secondsStyle_ is *"2-digit"*. 404 | 1. Let _nfOpts_ be OrdinaryObjectCreate(*null*). 405 | 1. Let _numberingSystem_ be _durationFormat_.[[NumberingSystem]]. 406 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"numberingSystem"*, _numberingSystem_). 407 | 1. If _secondsStyle_ is *"2-digit"*, then 408 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"minimumIntegerDigits"*, *2*𝔽). 409 | 1. If _signDisplayed_ is *false*, then 410 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"signDisplay"*, *"never"*). 411 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"useGrouping"*, *false*). 412 | 1. If _durationFormat_.[[FractionalDigits]] is *undefined*, then 413 | 1. Let _maximumFractionDigits_ be *9*𝔽. 414 | 1. Let _minimumFractionDigits_ be *+0*𝔽. 415 | 1. Else, 416 | 1. Let _maximumFractionDigits_ be _durationFormat_.[[FractionalDigits]]. 417 | 1. Let _minimumFractionDigits_ be _durationFormat_.[[FractionalDigits]]. 418 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"maximumFractionDigits"*, _maximumFractionDigits_). 419 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"minimumFractionDigits"*, _minimumFractionDigits_). 420 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"roundingMode"*, *"trunc"*). 421 | 1. Let _nf_ be ! Construct(%Intl.NumberFormat%, « _durationFormat_.[[Locale]], _nfOpts_ »). 422 | 1. Let _secondsParts_ be PartitionNumberPattern(_nf_, _secondsValue_). 423 | 1. For each Record { [[Type]], [[Value]] } _part_ of _secondsParts_, do 424 | 1. Append the Record { [[Type]]: _part_.[[Type]], [[Value]]: _part_.[[Value]], [[Unit]]: *"second"* } to _result_. 425 | 1. Return _result_. 426 | 427 |
428 | 429 | 430 |

431 | FormatNumericUnits ( 432 | _durationFormat_: a DurationFormat Object, 433 | _duration_: a Duration Record, 434 | _firstNumericUnit_: a String, 435 | _signDisplayed_: a Boolean, 436 | ): a List of Records 437 |

438 |
439 |
description
440 |
It creates the parts representing the elements of _duration_ that use *"numeric"* or *"2-digit"* style according to the effective locale and the formatting options of _durationFormat_.
441 |
442 | 443 | 444 | 1. Assert: _firstNumericUnit_ is *"hours"*, *"minutes"*, or *"seconds"*. 445 | 1. Let _numericPartsList_ be a new empty List. 446 | 1. Let _hoursValue_ be _duration_.[[Hours]]. 447 | 1. Let _hoursDisplay_ be _durationFormat_.[[HoursDisplay]]. 448 | 1. Let _minutesValue_ be _duration_.[[Minutes]]. 449 | 1. Let _minutesDisplay_ be _durationFormat_.[[MinutesDisplay]]. 450 | 1. Let _secondsValue_ be _duration_.[[Seconds]]. 451 | 1. If _duration_.[[Milliseconds]] is not 0 or _duration_.[[Microseconds]] is not 0 or _duration_.[[Nanoseconds]] is not 0, then 452 | 1. Set _secondsValue_ to _secondsValue_ + ComputeFractionalDigits(_durationFormat_, _duration_). 453 | 1. Let _secondsDisplay_ be _durationFormat_.[[SecondsDisplay]]. 454 | 1. Let _hoursFormatted_ be *false*. 455 | 1. If _firstNumericUnit_ is *"hours"*, then 456 | 1. If _hoursValue_ is not 0 or _hoursDisplay_ is *"always"*, then 457 | 1. Set _hoursFormatted_ to *true*. 458 | 1. If _secondsValue_ is not 0 or _secondsDisplay_ is *"always"*, then 459 | 1. Let _secondsFormatted_ be *true*. 460 | 1. Else, 461 | 1. Let _secondsFormatted_ be *false*. 462 | 1. Let _minutesFormatted_ be *false*. 463 | 1. If _firstNumericUnit_ is *"hours"* or _firstNumericUnit_ is *"minutes"*, then 464 | 1. If _hoursFormatted_ is *true* and _secondsFormatted_ is *true*, then 465 | 1. Set _minutesFormatted_ to *true*. 466 | 1. Else if _minutesValue_ is not 0 or _minutesDisplay_ is *"always"*, then 467 | 1. Set _minutesFormatted_ to *true*. 468 | 1. If _hoursFormatted_ is *true*, then 469 | 1. If _signDisplayed_ is *true*, then 470 | 1. If _hoursValue_ is 0 and DurationSign(_duration_) is -1, then 471 | 1. Set _hoursValue_ to ~negative-zero~. 472 | 1. Let _hoursParts_ be FormatNumericHours(_durationFormat_, _hoursValue_, _signDisplayed_). 473 | 1. Set _numericPartsList_ to the list-concatenation of _numericPartsList_ and _hoursParts_. 474 | 1. Set _signDisplayed_ to *false*. 475 | 1. If _minutesFormatted_ is *true*, then 476 | 1. If _signDisplayed_ is *true*, then 477 | 1. If _minutesValue_ is 0 and DurationSign(_duration_) is -1, then 478 | 1. Set _minutesValue_ to ~negative-zero~. 479 | 1. Let _minutesParts_ be FormatNumericMinutes(_durationFormat_, _minutesValue_, _hoursFormatted_, _signDisplayed_). 480 | 1. Set _numericPartsList_ to the list-concatenation of _numericPartsList_ and _minutesParts_. 481 | 1. Set _signDisplayed_ to *false*. 482 | 1. If _secondsFormatted_ is *true*, then 483 | 1. Let _secondsParts_ be FormatNumericSeconds(_durationFormat_, _secondsValue_, _minutesFormatted_, _signDisplayed_). 484 | 1. Set _numericPartsList_ to the list-concatenation of _numericPartsList_ and _secondsParts_. 485 | 1. Return _numericPartsList_. 486 | 487 |
488 | 489 | 490 |

ListFormatParts ( 491 | _durationFormat_: a DurationFormat Object 492 | _partitionedPartsList_: a List of Lists of Records, 493 | ): a List 494 |

495 |
496 |
description
497 |
It creates a List corresponding to the parts within the Lists in _partitionedPartsList_ according to the effective locale and the formatting options of _durationFormat_.
498 |
499 | 500 | 1. Let _lfOpts_ be OrdinaryObjectCreate(*null*). 501 | 1. Perform ! CreateDataPropertyOrThrow(_lfOpts_, *"type"*, *"unit"*). 502 | 1. Let _listStyle_ be _durationFormat_.[[Style]]. 503 | 1. If _listStyle_ is *"digital"*, then 504 | 1. Set _listStyle_ to *"short"*. 505 | 1. Perform ! CreateDataPropertyOrThrow(_lfOpts_, *"style"*, _listStyle_). 506 | 1. Let _lf_ be ! Construct(%Intl.ListFormat%, « _durationFormat_.[[Locale]], _lfOpts_ »). 507 | 1. Let _strings_ be a new empty List. 508 | 1. For each element _parts_ of _partitionedPartsList_, do 509 | 1. Let _string_ be the empty String. 510 | 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do 511 | 1. Set _string_ to the string-concatenation of _string_ and _part_.[[Value]]. 512 | 1. Append _string_ to _strings_. 513 | 1. Let _formattedPartsList_ be CreatePartsFromList(_lf_, _strings_). 514 | 1. Let _partitionedPartsIndex_ be 0. 515 | 1. Let _partitionedLength_ be the number of elements in _partitionedPartsList_. 516 | 1. Let _flattenedPartsList_ be a new empty List. 517 | 1. For each Record { [[Type]], [[Value]] } _listPart_ in _formattedPartsList_, do 518 | 1. If _listPart_.[[Type]] is *"element"*, then 519 | 1. Assert: _partitionedPartsIndex_ < _partitionedLength_. 520 | 1. Let _parts_ be _partitionedPartsList_[_partitionedPartsIndex_]. 521 | 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do 522 | 1. Append _part_ to _flattenedPartsList_. 523 | 1. Set _partitionedPartsIndex_ to _partitionedPartsIndex_ + 1. 524 | 1. Else, 525 | 1. Assert: _listPart_.[[Type]] is *"literal"*. 526 | 1. Append the Record { [[Type]]: *"literal"*, [[Value]]: _listPart_.[[Value]], [[Unit]]: ~empty~ } to _flattenedPartsList_. 527 | 1. Return _flattenedPartsList_. 528 | 529 |
530 | 531 | 532 |

533 | PartitionDurationFormatPattern ( 534 | _durationFormat_: a DurationFormat, 535 | _duration_: a Duration Record, 536 | ): a List 537 |

538 |
539 |
description
540 |
It creates the corresponding parts for _duration_ according to the effective locale and the formatting options of _durationFormat_.
541 |
542 | 543 | 544 | 1. Let _result_ be a new empty List. 545 | 1. Let _signDisplayed_ be *true*. 546 | 1. Let _numericUnitFound_ be *false*. 547 | 1. While _numericUnitFound_ is *false*, repeat for each row in in table order, except the header row: 548 | 1. Let _value_ be the value of _duration_'s field whose name is the Value Field value of the current row. 549 | 1. Let _style_ be the value of _durationFormat_'s internal slot whose name is the Style Slot value of the current row. 550 | 1. Let _display_ be the value of _durationFormat_'s internal slot whose name is the Display Slot value of the current row. 551 | 1. Let _unit_ be the Unit value of the current row. 552 | 1. If _style_ is *"numeric"* or *"2-digit"*, then 553 | 1. Let _numericPartsList_ be FormatNumericUnits(_durationFormat_, _duration_, _unit_, _signDisplayed_). 554 | 1. If _numericPartsList_ is not empty, append _numericPartsList_ to _result_. 555 | 1. Set _numericUnitFound_ to *true*. 556 | 1. Else, 557 | 1. Let _nfOpts_ be OrdinaryObjectCreate(*null*). 558 | 1. If _unit_ is *"seconds"*, *"milliseconds"*, or *"microseconds"*, then 559 | 1. If NextUnitFractional(_durationFormat_, _unit_) is *true*, then 560 | 1. Set _value_ to _value_ + ComputeFractionalDigits(_durationFormat_, _duration_). 561 | 1. If _durationFormat_.[[FractionalDigits]] is *undefined*, then 562 | 1. Let _maximumFractionDigits_ be *9*𝔽. 563 | 1. Let _minimumFractionDigits_ be *+0*𝔽. 564 | 1. Else, 565 | 1. Let _maximumFractionDigits_ be _durationFormat_.[[FractionalDigits]]. 566 | 1. Let _minimumFractionDigits_ be _durationFormat_.[[FractionalDigits]]. 567 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"maximumFractionDigits"*, _maximumFractionDigits_). 568 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"minimumFractionDigits"*, _minimumFractionDigits_). 569 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"roundingMode"*, *"trunc"*). 570 | 1. Set _numericUnitFound_ to *true*. 571 | 1. If _value_ is not 0 or _display_ is *"always"*, then 572 | 1. Let _numberingSystem_ be _durationFormat_.[[NumberingSystem]]. 573 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"numberingSystem"*, _numberingSystem_). 574 | 1. If _signDisplayed_ is *true*, then 575 | 1. Set _signDisplayed_ to *false*. 576 | 1. If _value_ is 0 and DurationSign(_duration_) is -1, then 577 | 1. Set _value_ to ~negative-zero~. 578 | 1. Else, 579 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"signDisplay"*, *"never"*). 580 | 1. Let _numberFormatUnit_ be the NumberFormat Unit value of the current row. 581 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"style"*, *"unit"*). 582 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"unit"*, _numberFormatUnit_). 583 | 1. Perform ! CreateDataPropertyOrThrow(_nfOpts_, *"unitDisplay"*, _style_). 584 | 1. Let _nf_ be ! Construct(%Intl.NumberFormat%, « _durationFormat_.[[Locale]], _nfOpts_ »). 585 | 1. Let _parts_ be PartitionNumberPattern(_nf_, _value_). 586 | 1. Let _list_ be a new empty List. 587 | 1. For each Record { [[Type]], [[Value]] } _part_ of _parts_, do 588 | 1. Append the Record { [[Type]]: _part_.[[Type]], [[Value]]: _part_.[[Value]], [[Unit]]: _numberFormatUnit_ } to _list_. 589 | 1. Append _list_ to _result_. 590 | 1. Return ListFormatParts(_durationFormat_, _result_). 591 | 592 | 593 | 594 | DurationFormat instance internal slots and properties relevant to PartitionDurationFormatPattern 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 |
Value FieldStyle SlotDisplay SlotUnitNumberFormat Unit
[[Years]][[YearsStyle]][[YearsDisplay]]*"years"**"year"*
[[Months]][[MonthsStyle]][[MonthsDisplay]]*"months"**"month"*
[[Weeks]][[WeeksStyle]][[WeeksDisplay]]*"weeks"**"week"*
[[Days]][[DaysStyle]][[DaysDisplay]]*"days"**"day"*
[[Hours]][[HoursStyle]][[HoursDisplay]]*"hours"**"hour"*
[[Minutes]][[MinutesStyle]][[MinutesDisplay]]*"minutes"**"minute"*
[[Seconds]][[SecondsStyle]][[SecondsDisplay]]*"seconds"**"second"*
[[Milliseconds]][[MillisecondsStyle]][[MillisecondsDisplay]]*"milliseconds"**"millisecond"*
[[Microseconds]][[MicrosecondsStyle]][[MicrosecondsDisplay]]*"microseconds"**"microsecond"*
[[Nanoseconds]][[NanosecondsStyle]][[NanosecondsDisplay]]*"nanoseconds"**"nanosecond"*
676 |
677 |
678 |
679 | 680 | 681 |

The Intl.DurationFormat Constructor

682 | 683 |

The DurationFormat constructor is the %Intl.DurationFormat% intrinsic object and a standard built-in property of the Intl object. Behaviour common to all service constructor properties of the Intl object is specified in .

684 | 685 | 686 |

Intl.DurationFormat ( [ _locales_ [ , _options_ ] ] )

687 | 688 |

When the `Intl.DurationFormat` function is called with optional arguments _locales_ and _options_, the following steps are taken:

689 | 690 | 691 | 1. If NewTarget is *undefined*, throw a *TypeError* exception. 692 | 1. Let _durationFormat_ be ? OrdinaryCreateFromConstructor(NewTarget, *"%Intl.DurationFormatPrototype%"*, « [[InitializedDurationFormat]], [[Locale]], [[NumberingSystem]], [[Style]], [[YearsStyle]], [[YearsDisplay]], [[MonthsStyle]], [[MonthsDisplay]], [[WeeksStyle]], [[WeeksDisplay]], [[DaysStyle]], [[DaysDisplay]], [[HoursStyle]], [[HoursDisplay]], [[MinutesStyle]], [[MinutesDisplay]], [[SecondsStyle]], [[SecondsDisplay]], [[MillisecondsStyle]], [[MillisecondsDisplay]], [[MicrosecondsStyle]], [[MicrosecondsDisplay]], [[NanosecondsStyle]], [[NanosecondsDisplay]], [[HourMinuteSeparator]], [[MinuteSecondSeparator]], [[FractionalDigits]] »). 693 | 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). 694 | 1. Let _options_ be ? GetOptionsObject(_options_). 695 | 1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, ~string~, « *"lookup"*, *"best fit"* », *"best fit"*). 696 | 1. Let _numberingSystem_ be ? GetOption(_options_, *"numberingSystem"*, ~string~, ~empty~, *undefined*). 697 | 1. If _numberingSystem_ is not *undefined*, then 698 | 1. If _numberingSystem_ does not match the Unicode Locale Identifier `type` nonterminal, throw a *RangeError* exception. 699 | 1. Let _opt_ be the Record { [[localeMatcher]]: _matcher_, [[nu]]: _numberingSystem_ }. 700 | 1. Let _r_ be ResolveLocale(%Intl.DurationFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %Intl.DurationFormat%.[[RelevantExtensionKeys]], %Intl.DurationFormat%.[[LocaleData]]). 701 | 1. Set _durationFormat_.[[Locale]] to _r_.[[Locale]]. 702 | 1. Let _resolvedLocaleData_ be _r_.[[LocaleData]]. 703 | 1. Let _digitalFormat_ be _resolvedLocaleData_.[[DigitalFormat]]. 704 | 1. Set _durationFormat_.[[HourMinuteSeparator]] to _digitalFormat_.[[HourMinuteSeparator]]. 705 | 1. Set _durationFormat_.[[MinuteSecondSeparator]] to _digitalFormat_.[[MinuteSecondSeparator]]. 706 | 1. Set _durationFormat_.[[NumberingSystem]] to _r_.[[nu]]. 707 | 1. Let _style_ be ? GetOption(_options_, *"style"*, ~string~, « *"long"*, *"short"*, *"narrow"*, *"digital"* », *"short"*). 708 | 1. Set _durationFormat_.[[Style]] to _style_. 709 | 1. Let _prevStyle_ be the empty String. 710 | 1. For each row of , except the header row, in table order, do 711 | 1. Let _styleSlot_ be the Style Slot value of the current row. 712 | 1. Let _displaySlot_ be the Display Slot value of the current row. 713 | 1. Let _unit_ be the Unit value of the current row. 714 | 1. Let _valueList_ be the Values value of the current row. 715 | 1. Let _digitalBase_ be the Digital Default value of the current row. 716 | 1. Let _unitOptions_ be ? GetDurationUnitOptions(_unit_, _options_, _style_, _valueList_, _digitalBase_, _prevStyle_, _digitalFormat_.[[TwoDigitHours]]). 717 | 1. Set the value of the _styleSlot_ slot of _durationFormat_ to _unitOptions_.[[Style]]. 718 | 1. Set the value of the _displaySlot_ slot of _durationFormat_ to _unitOptions_.[[Display]]. 719 | 1. If _unit_ is one of *"hours"*, *"minutes"*, *"seconds"*, *"milliseconds"*, or *"microseconds"*, then 720 | 1. Set _prevStyle_ to _unitOptions_.[[Style]]. 721 | 1. Set _durationFormat_.[[FractionalDigits]] to ? GetNumberOption(_options_, *"fractionalDigits"*, 0, 9, *undefined*). 722 | 1. Return _durationFormat_. 723 | 724 | 725 | Internal slots and property names of DurationFormat instances relevant to Intl.DurationFormat constructor 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 |
Style SlotDisplay SlotUnitValuesDigital Default
[[YearsStyle]][[YearsDisplay]]*"years"*« *"long"*, *"short"*, *"narrow"* »*"short"*
[[MonthsStyle]][[MonthsDisplay]]*"months"*« *"long"*, *"short"*, *"narrow"* »*"short"*
[[WeeksStyle]][[WeeksDisplay]]*"weeks"*« *"long"*, *"short"*, *"narrow"* »*"short"*
[[DaysStyle]][[DaysDisplay]]*"days"*« *"long"*, *"short"*, *"narrow"* »*"short"*
[[HoursStyle]][[HoursDisplay]]*"hours"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"*, *"2-digit"* »
*"numeric"*
[[MinutesStyle]][[MinutesDisplay]]*"minutes"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"*, *"2-digit"* »
*"numeric"*
[[SecondsStyle]][[SecondsDisplay]]*"seconds"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"*, *"2-digit"* »
*"numeric"*
[[MillisecondsStyle]][[MillisecondsDisplay]]*"milliseconds"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"* »
*"numeric"*
[[MicrosecondsStyle]][[MicrosecondsDisplay]]*"microseconds"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"* »
*"numeric"*
[[NanosecondsStyle]][[NanosecondsDisplay]]*"nanoseconds"*« *"long"*, *"short"*, *"narrow"*,
*"numeric"* »
*"numeric"*
807 |
808 |
809 |
810 | 811 | 812 |

Properties of the Intl.DurationFormat Constructor

813 | 814 |

The Intl.DurationFormat constructor has the following properties:

815 | 816 | 817 |

Intl.DurationFormat.prototype

818 | 819 |

The value of `Intl.DurationFormat.prototype` is %Intl.DurationFormat.prototype%.

820 | 821 |

This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }.

822 |
823 | 824 | 825 |

Intl.DurationFormat.supportedLocalesOf ( _locales_ [ , _options_ ] )

826 | 827 |

When the `supportedLocalesOf` method is called with arguments _locales_ and _options_, the following steps are taken:

828 | 829 | 830 | 1. Let _availableLocales_ be %Intl.DurationFormat%.[[AvailableLocales]]. 831 | 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). 832 | 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_). 833 | 834 |
835 | 836 | 837 |

Internal slots

838 | 839 |

The value of the [[AvailableLocales]] internal slot is implementation defined within the constraints described in .

840 | 841 |

The value of the [[RelevantExtensionKeys]] internal slot is « *"nu"* ».

842 | 843 |

The value of the [[LocaleData]] internal slot is implementation defined within the constraints described in and the following additional constraints for all locale values _locale_:

844 | 845 |
    846 |
  • [[LocaleData]].[[<_locale_>]].[[nu]] must be a List as specified in and must not include the values *"native"*, *"traditio"*, or *"finance"**.
  • 847 |
  • [[LocaleData]].[[<_locale_>]].[[DigitalFormat]] must be a Record with keys corresponding to each numbering system available for the given locale, with Record values containing the following fields: 848 |
      849 |
    • [[HourMinuteSeparator]] is a String value that is the appropriate separator between hours and minutes for that combination of locale, numbering system, and unit when using *"numeric"* or *"2-digit"* styles
    • 850 |
    • [[MinuteSecondSeparator]] is a String value that is the appropriate separator between minutes and seconds for that combination of locale, numbering system, and unit when using *"numeric"* or *"2-digit"* styles.
    • 851 |
    • [[TwoDigitHours]] is a Boolean value indicating whether hours are always displayed using two digits when the *"numeric"* style is used.
    • 852 |
    853 |
  • 854 |
855 | 856 | It is recommended that implementations use the locale data provided by the Common Locale Data Repository (available at http://cldr.unicode.org/). 857 |
858 |
859 | 860 | 861 |

Properties of the Intl.DurationFormat Prototype Object

862 | 863 |

The Intl.DurationFormat prototype object is itself an ordinary object. %Intl.DurationFormat.prototype% is not an Intl.DurationFormat instance and does not have an [[InitializedDurationFormat]] internal slot or any of the other internal slots of Intl.DurationFormat instance objects.

864 | 865 | 866 |

Intl.DurationFormat.prototype.constructor

867 | 868 |

The initial value of `Intl.DurationFormat.prototype.constructor` is the intrinsic object %Intl.DurationFormat%.

869 |
870 | 871 | 872 |

Intl.DurationFormat.prototype [ @@toStringTag ]

873 | 874 |

The initial value of the @@toStringTag property is the string value *"Intl.DurationFormat"*.

875 |

This property has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *true* }.

876 |
877 | 878 | 879 |

Intl.DurationFormat.prototype.format ( _duration_ )

880 | 881 |

When the `format` method is called with an argument _duration_, the following steps are taken:

882 | 883 | 884 | 1. Let _df_ be the *this* value. 885 | 1. Perform ? RequireInternalSlot(_df_, [[InitializedDurationFormat]]). 886 | 1. Let _record_ be ? ToDurationRecord(_duration_). 887 | 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _record_). 888 | 1. Let _result_ be the empty String. 889 | 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do 890 | 1. Set _result_ to the string-concatenation of _result_ and _part_.[[Value]]. 891 | 1. Return _result_. 892 | 893 |
894 | 895 |

Intl.DurationFormat.prototype.formatToParts ( _duration_ )

896 | 897 |

When the `formatToParts` method is called with an argument _duration_, the following steps are taken:

898 | 899 | 900 | 1. Let _df_ be the *this* value. 901 | 1. Perform ? RequireInternalSlot(_df_, [[InitializedDurationFormat]]). 902 | 1. Let _record_ be ? ToDurationRecord(_duration_). 903 | 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _record_). 904 | 1. Let _result_ be ! ArrayCreate(0). 905 | 1. Let _n_ be 0. 906 | 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do 907 | 1. Let _obj_ be OrdinaryObjectCreate(%Object.prototype%). 908 | 1. Perform ! CreateDataPropertyOrThrow(_obj_, *"type"*, _part_.[[Type]]). 909 | 1. Perform ! CreateDataPropertyOrThrow(_obj_, *"value"*, _part_.[[Value]]). 910 | 1. If _part_.[[Unit]] is not ~empty~, perform ! CreateDataPropertyOrThrow(_obj_, *"unit"*, _part_.[[Unit]]). 911 | 1. Perform ! CreateDataPropertyOrThrow(_result_, ! ToString(_n_), _obj_). 912 | 1. Set _n_ to _n_ + 1. 913 | 1. Return _result_. 914 | 915 |
916 | 917 |

Intl.DurationFormat.prototype.resolvedOptions ( )

918 | 919 |

This function provides access to the locale and options computed during initialization of the object.

920 | 921 | 922 | 1. Let _df_ be the *this* value. 923 | 1. Perform ? RequireInternalSlot(_df_, [[InitializedDurationFormat]]). 924 | 1. Let _options_ be OrdinaryObjectCreate(%Object.prototype%). 925 | 1. For each row of , except the header row, in table order, do 926 | 1. Let _p_ be the Property value of the current row. 927 | 1. Let _v_ be the value of _df_'s internal slot whose name is the Internal Slot value of the current row. 928 | 1. If _p_ is *"fractionalDigits"*, then 929 | 1. If _v_ is not *undefined*, set _v_ to 𝔽(_v_). 930 | 1. Else, 931 | 1. Assert: _v_ is not *undefined*. 932 | 1. If _v_ is *"fractional"*, then 933 | 1. Assert: The Internal Slot value of the current row is [[MillisecondsStyle]], [[MicrosecondsStyle]], or [[NanosecondsStyle]] . 934 | 1. Set _v_ to *"numeric"*. 935 | 1. If _v_ is not *undefined*, then 936 | 1. Perform ! CreateDataPropertyOrThrow(_options_, _p_, _v_). 937 | 1. Return _options_. 938 | 939 | 940 | 941 | Resolved Options of DurationFormat Instances 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 |
Internal SlotProperty
[[Locale]]*"locale"*
[[NumberingSystem]]*"numberingSystem"*
[[Style]]*"style"*
[[YearsStyle]]*"years"*
[[YearsDisplay]]*"yearsDisplay"*
[[MonthsStyle]]*"months"*
[[MonthsDisplay]]*"monthsDisplay"*
[[WeeksStyle]]*"weeks"*
[[WeeksDisplay]]*"weeksDisplay"*
[[DaysStyle]]*"days"*
[[DaysDisplay]]*"daysDisplay"*
[[HoursStyle]]*"hours"*
[[HoursDisplay]]*"hoursDisplay"*
[[MinutesStyle]]*"minutes"*
[[MinutesDisplay]]*"minutesDisplay"*
[[SecondsStyle]]*"seconds"*
[[SecondsDisplay]]*"secondsDisplay"*
[[MillisecondsStyle]]*"milliseconds"*
[[MillisecondsDisplay]]*"millisecondsDisplay"*
[[MicrosecondsStyle]]*"microseconds"*
[[MicrosecondsDisplay]]*"microsecondsDisplay"*
[[NanosecondsStyle]]*"nanoseconds"*
[[NanosecondsDisplay]]*"nanosecondsDisplay"*
[[FractionalDigits]]*"fractionalDigits"*
1046 |
1047 |
1048 |
1049 | 1050 | 1051 |

Properties of Intl.DurationFormat Instances

1052 | 1053 |

Intl.DurationFormat instances inherit properties from %Intl.DurationFormat.prototype%.

1054 |

Intl.DurationFormat instances have an [[InitializedDurationFormat]] internal slot.

1055 |

Intl.DurationFormat instances also have several internal slots that are computed by the constructor:

1056 | 1057 |
    1058 |
  • [[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
  • 1059 |
  • [[NumberingSystem]] is a String value with the *"type"* given in Unicode Technical Standard 35 for the numbering system used for formatting.
  • 1060 |
  • [[Style]] is one of the String values *"long"*, *"short"*, *"narrow"*, or *"digital"* identifying the duration formatting style used.
  • 1061 |
  • [[YearsStyle]] is one of the String values *"long"*, *"short"*, or *"narrow"* identifying the formatting style used for the years field.
  • 1062 |
  • [[YearsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the years field.
  • 1063 |
  • [[MonthsStyle]] is one of the String values *"long"*, *"short"*, or *"narrow"* identifying the formatting style used for the months field.
  • 1064 |
  • [[MonthsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the months field.
  • 1065 |
  • [[WeeksStyle]] is one of the String values *"long"*, *"short"*, or *"narrow"* identifying the formatting style used for the weeks field.
  • 1066 |
  • [[WeeksDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the weeks field.
  • 1067 |
  • [[DaysStyle]] is one of the String values *"long"*, *"short"*, or *"narrow"* identifying the formatting style used for the days field.
  • 1068 |
  • [[DaysDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the days field.
  • 1069 |
  • [[HoursStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, *"2-digit"*, or *"numeric"* identifying the formatting style used for the hours field.
  • 1070 |
  • [[HoursDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the hours field.
  • 1071 |
  • [[MinutesStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, *"2-digit"*, or *"numeric"* identifying the formatting style used for the minutes field.
  • 1072 |
  • [[MinutesDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the minutes field.
  • 1073 |
  • [[SecondsStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, *"2-digit"*, or *"numeric"* identifying the formatting style used for the seconds field.
  • 1074 |
  • [[SecondsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the seconds field.
  • 1075 |
  • [[MillisecondsStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, or *"fractional"* identifying the formatting style used for the milliseconds field.
  • 1076 |
  • [[MillisecondsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the milliseconds field.
  • 1077 |
  • [[MicrosecondsStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, or *"fractional"* identifying the formatting style used for the microseconds field.
  • 1078 |
  • [[MicrosecondsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the microseconds field.
  • 1079 |
  • [[NanosecondsStyle]] is one of the String values *"long"*, *"short"*, *"narrow"*, or *"fractional"* identifying the formatting style used for the nanoseconds field.
  • 1080 |
  • [[NanosecondsDisplay]] is one of the String values *"auto"* or *"always"* identifying when to display the nanoseconds field.
  • 1081 |
  • [[HourMinuteSeparator]] is a String value identifying the separator to be used between hours and minutes when both fields are displayed and both fields are formatted using numeric styles.
  • 1082 |
  • [[MinuteSecondSeparator]] is a String value identifying the separator to be used between minutes and seconds when both fields are displayed and both fields are formatted using numeric styles.
  • 1083 |
  • [[FractionalDigits]] is a non-negative integer, identifying the number of fractional digits to be used with numeric styles, or is *undefined*.
  • 1084 |
1085 |
1086 |
1087 | --------------------------------------------------------------------------------