diff --git a/index.html b/index.html index 1c02984..f5f2e8f 100644 --- a/index.html +++ b/index.html @@ -452,25 +452,68 @@ }; function findActiveClause(root, path) { - let clauses = getChildClauses(root); path = path || []; - for (let $clause of clauses) { - let rect = $clause.getBoundingClientRect(); + let visibleClauses = getVisibleClauses(root, path); + let midpoint = Math.floor(window.innerHeight / 2); + + for (let [$clause, path] of visibleClauses) { + let { top: clauseTop, bottom: clauseBottom } = $clause.getBoundingClientRect(); + let isFullyVisibleAboveTheFold = + clauseTop > 0 && clauseTop < midpoint && clauseBottom < window.innerHeight; + if (isFullyVisibleAboveTheFold) { + return path; + } + } + + visibleClauses.sort(([, pathA], [, pathB]) => pathB.length - pathA.length); + for (let [$clause, path] of visibleClauses) { + let { top: clauseTop, bottom: clauseBottom } = $clause.getBoundingClientRect(); let $header = $clause.querySelector('h1'); + let clauseStyles = getComputedStyle($clause); let marginTop = Math.max( - parseInt(getComputedStyle($clause)['margin-top']), + 0, + parseInt(clauseStyles['margin-top']), parseInt(getComputedStyle($header)['margin-top']) ); - - if (rect.top - marginTop <= 1 && rect.bottom > 0) { - return findActiveClause($clause, path.concat($clause)) || path; + let marginBottom = Math.max(0, parseInt(clauseStyles['margin-bottom'])); + let crossesMidpoint = + clauseTop - marginTop <= midpoint && clauseBottom + marginBottom >= midpoint; + if (crossesMidpoint) { + return path; } } return path; } +function getVisibleClauses(root, path) { + let childClauses = getChildClauses(root); + path = path || []; + + let result = []; + + let seenVisibleClause = false; + for (let $clause of childClauses) { + let { top: clauseTop, bottom: clauseBottom } = $clause.getBoundingClientRect(); + let isPartiallyVisible = + (clauseTop > 0 && clauseTop < window.innerHeight) || + (clauseBottom > 0 && clauseBottom < window.innerHeight) || + (clauseTop < 0 && clauseBottom > window.innerHeight); + + if (isPartiallyVisible) { + seenVisibleClause = true; + let innerPath = path.concat($clause); + result.push([$clause, innerPath]); + result.push(...getVisibleClauses($clause, innerPath)); + } else if (seenVisibleClause) { + break; + } + } + + return result; +} + function* getChildClauses(root) { for (let el of root.children) { switch (el.nodeName) { @@ -1162,12 +1205,40 @@ return [...menu.$menu.querySelectorAll('.active')].map(getTocPath).filter(p => p != null); } -function loadStateFromSessionStorage() { - if (!window.sessionStorage || typeof menu === 'undefined' || window.navigating) { +function initTOCExpansion(visibleItemLimit) { + // Initialize to a reasonable amount of TOC expansion: + // * Expand any full-breadth nesting level up to visibleItemLimit. + // * Expand any *single-item* level while under visibleItemLimit (even if that pushes over it). + + // Limit to initialization by bailing out if any parent item is already expanded. + const tocItems = Array.from(document.querySelectorAll('#menu-toc li')); + if (tocItems.some(li => li.classList.contains('active') && li.querySelector('li'))) { return; } - if (sessionStorage.referencePaneState != null) { - let state = JSON.parse(sessionStorage.referencePaneState); + + const selfAndSiblings = maybe => Array.from(maybe?.parentNode.children ?? []); + let currentLevelItems = selfAndSiblings(tocItems[0]); + let availableCount = visibleItemLimit - currentLevelItems.length; + while (availableCount > 0 && currentLevelItems.length) { + const nextLevelItems = currentLevelItems.flatMap(li => selfAndSiblings(li.querySelector('li'))); + availableCount -= nextLevelItems.length; + if (availableCount > 0 || currentLevelItems.length === 1) { + // Expand parent items of the next level down (i.e., current-level items with children). + for (const ol of new Set(nextLevelItems.map(li => li.parentNode))) { + ol.closest('li').classList.add('active'); + } + } + currentLevelItems = nextLevelItems; + } +} + +function initState() { + if (typeof menu === 'undefined' || window.navigating) { + return; + } + const storage = typeof sessionStorage !== 'undefined' ? sessionStorage : Object.create(null); + if (storage.referencePaneState != null) { + let state = JSON.parse(storage.referencePaneState); if (state != null) { if (state.type === 'ref') { let entry = menu.search.biblio.byId[state.id]; @@ -1181,39 +1252,36 @@ referencePane.showSDOsBody(sdos, state.id); } } - delete sessionStorage.referencePaneState; + delete storage.referencePaneState; } } - if (sessionStorage.activeTocPaths != null) { - document - .getElementById('menu-toc') - .querySelectorAll('.active') - .forEach(e => { - e.classList.remove('active'); - }); - let active = JSON.parse(sessionStorage.activeTocPaths); + if (storage.activeTocPaths != null) { + document.querySelectorAll('#menu-toc li.active').forEach(li => li.classList.remove('active')); + let active = JSON.parse(storage.activeTocPaths); active.forEach(activateTocPath); - delete sessionStorage.activeTocPaths; + delete storage.activeTocPaths; + } else { + initTOCExpansion(20); } - if (sessionStorage.searchValue != null) { - let value = JSON.parse(sessionStorage.searchValue); + if (storage.searchValue != null) { + let value = JSON.parse(storage.searchValue); menu.search.$searchBox.value = value; menu.search.search(value); - delete sessionStorage.searchValue; + delete storage.searchValue; } - if (sessionStorage.tocScroll != null) { - let tocScroll = JSON.parse(sessionStorage.tocScroll); + if (storage.tocScroll != null) { + let tocScroll = JSON.parse(storage.tocScroll); menu.$toc.scrollTop = tocScroll; - delete sessionStorage.tocScroll; + delete storage.tocScroll; } } -document.addEventListener('DOMContentLoaded', loadStateFromSessionStorage); +document.addEventListener('DOMContentLoaded', initState); -window.addEventListener('pageshow', loadStateFromSessionStorage); +window.addEventListener('pageshow', initState); window.addEventListener('beforeunload', () => { if (!window.sessionStorage || typeof menu === 'undefined') { @@ -1226,33 +1294,128 @@ }); 'use strict'; -let decimalBullet = Array.from({ length: 100 }, (a, i) => '' + (i + 1)); -let alphaBullet = Array.from({ length: 26 }, (a, i) => String.fromCharCode('a'.charCodeAt(0) + i)); - -// prettier-ignore -let romanBullet = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x', 'xi', 'xii', 'xiii', 'xiv', 'xv', 'xvi', 'xvii', 'xviii', 'xix', 'xx', 'xxi', 'xxii', 'xxiii', 'xxiv', 'xxv']; -// prettier-ignore -let bullets = [decimalBullet, alphaBullet, romanBullet, decimalBullet, alphaBullet, romanBullet]; - -function addStepNumberText(ol, parentIndex) { - for (let i = 0; i < ol.children.length; ++i) { - let child = ol.children[i]; - let index = parentIndex.concat([i]); - let applicable = bullets[Math.min(index.length - 1, 5)]; - let span = document.createElement('span'); - span.textContent = (applicable[i] || '?') + '. '; - span.style.fontSize = '0'; - span.setAttribute('aria-hidden', 'true'); - child.prepend(span); - let sublist = child.querySelector('ol'); - if (sublist != null) { - addStepNumberText(sublist, index); + +// Manually prefix algorithm step list items with hidden counter representations +// corresponding with their markers so they get selected and copied with content. +// We read list-style-type to avoid divergence with the style sheet, but +// for efficiency assume that all lists at the same nesting depth use the same +// style (except for those associated with replacement steps). +// We also precompute some initial items for each supported style type. +// https://w3c.github.io/csswg-drafts/css-counter-styles/ + +const lowerLetters = Array.from({ length: 26 }, (_, i) => + String.fromCharCode('a'.charCodeAt(0) + i) +); +// Implement the lower-alpha 'alphabetic' algorithm, +// adjusting for indexing from 0 rather than 1. +// https://w3c.github.io/csswg-drafts/css-counter-styles/#simple-alphabetic +// https://w3c.github.io/csswg-drafts/css-counter-styles/#alphabetic-system +const lowerAlphaTextForIndex = i => { + let S = ''; + for (const N = lowerLetters.length; i >= 0; i--) { + S = lowerLetters[i % N] + S; + i = Math.floor(i / N); + } + return S; +}; + +const weightedLowerRomanSymbols = Object.entries({ + m: 1000, + cm: 900, + d: 500, + cd: 400, + c: 100, + xc: 90, + l: 50, + xl: 40, + x: 10, + ix: 9, + v: 5, + iv: 4, + i: 1, +}); +// Implement the lower-roman 'additive' algorithm, +// adjusting for indexing from 0 rather than 1. +// https://w3c.github.io/csswg-drafts/css-counter-styles/#simple-numeric +// https://w3c.github.io/csswg-drafts/css-counter-styles/#additive-system +const lowerRomanTextForIndex = i => { + let value = i + 1; + let S = ''; + for (const [symbol, weight] of weightedLowerRomanSymbols) { + if (!value) break; + if (weight > value) continue; + const reps = Math.floor(value / weight); + S += symbol.repeat(reps); + value -= weight * reps; + } + return S; +}; + +// Memoize pure index-to-text functions with an exposed cache for fast retrieval. +const makeCounter = (pureGetTextForIndex, precomputeCount = 30) => { + const cache = Array.from({ length: precomputeCount }, (_, i) => pureGetTextForIndex(i)); + const getTextForIndex = i => { + if (i >= cache.length) cache[i] = pureGetTextForIndex(i); + return cache[i]; + }; + return { getTextForIndex, cache }; +}; + +const counterByStyle = { + __proto__: null, + decimal: makeCounter(i => String(i + 1)), + 'lower-alpha': makeCounter(lowerAlphaTextForIndex), + 'upper-alpha': makeCounter(i => lowerAlphaTextForIndex(i).toUpperCase()), + 'lower-roman': makeCounter(lowerRomanTextForIndex), + 'upper-roman': makeCounter(i => lowerRomanTextForIndex(i).toUpperCase()), +}; +const fallbackCounter = makeCounter(() => '?'); +const counterByDepth = []; + +function addStepNumberText( + ol, + depth = 0, + special = [...ol.classList].some(c => c.startsWith('nested-')) +) { + let counter = !special && counterByDepth[depth]; + if (!counter) { + const counterStyle = getComputedStyle(ol)['list-style-type']; + counter = counterByStyle[counterStyle]; + if (!counter) { + console.warn('unsupported list-style-type', { + ol, + counterStyle, + id: ol.closest('[id]')?.getAttribute('id'), + }); + counterByStyle[counterStyle] = fallbackCounter; + counter = fallbackCounter; } + if (!special) { + counterByDepth[depth] = counter; + } + } + const { cache, getTextForIndex } = counter; + let i = (Number(ol.getAttribute('start')) || 1) - 1; + for (const li of ol.children) { + const marker = document.createElement('span'); + marker.textContent = `${i < cache.length ? cache[i] : getTextForIndex(i)}. `; + marker.setAttribute('aria-hidden', 'true'); + const attributesContainer = li.querySelector('.attributes-tag'); + if (attributesContainer == null) { + li.prepend(marker); + } else { + attributesContainer.insertAdjacentElement('afterend', marker); + } + for (const sublist of li.querySelectorAll(':scope > ol')) { + addStepNumberText(sublist, depth + 1, special); + } + i++; } } + document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('emu-alg > ol').forEach(ol => { - addStepNumberText(ol, []); + addStepNumberText(ol); }); }); @@ -1364,6 +1527,10 @@ transition: background-color 0.25s ease; cursor: pointer; } +var.field { + font: inherit; + color: inherit; +} var.referenced0 { color: inherit; @@ -1447,6 +1614,10 @@ list-style-type: lower-roman; } +emu-alg [aria-hidden='true'] { + font-size: 0; +} + emu-eqn { display: block; margin-left: 4em; @@ -1498,7 +1669,7 @@ margin-bottom: 0; } -emu-table td code { +emu-table:not(.code) td code { white-space: normal; } @@ -2457,19 +2628,19 @@ } [normative-optional], +[deprecated], [legacy] { border-left: 5px solid #ff6600; padding: 0.5em; - display: block; background: #ffeedd; } -.clause-attributes-tag { +.attributes-tag { text-transform: uppercase; color: #884400; } -.clause-attributes-tag a { +.attributes-tag a { color: #884400; } @@ -2541,61 +2712,61 @@

1.1.1 Duration Records

Meaning - [[Years]] + [[Years]] The number of years in the duration. - [[Months]] + [[Months]] The number of months in the duration. - [[Weeks]] + [[Weeks]] The number of weeks in the duration. - [[Days]] + [[Days]] The number of days in the duration. - [[Hours]] + [[Hours]] The number of hours in the duration. - [[Minutes]] + [[Minutes]] The number of minutes in the duration. - [[Seconds]] + [[Seconds]] The number of seconds in the duration. - [[Milliseconds]] + [[Milliseconds]] The number of milliseconds in the duration. - [[Microseconds]] + [[Microseconds]] The number of microseconds in the duration. - [[Nanoseconds]] + [[Nanoseconds]] The number of nanoseconds in the duration. @@ -2614,7 +2785,7 @@

1.1.2 ToIntegerIfIntegral ( argument

1.1.3 ToDurationRecord ( input )

The abstract operation ToDurationRecord takes argument input (an ECMAScript language value) and returns either a normal completion containing a Duration Record, or an abrupt completion. It converts a given object that represents a Duration into a Duration Record. It performs the following steps when called:

-
  1. If Type(input) is not Object, then
    1. If Type(input) is String, throw a RangeError exception.
    2. Throw a TypeError exception.
  2. Let result be a new Duration Record with each field set to 0.
  3. Let days be ? Get(input, "days").
  4. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
  5. Let hours be ? Get(input, "hours").
  6. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
  7. Let microseconds be ? Get(input, "microseconds").
  8. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
  9. Let milliseconds be ? Get(input, "milliseconds").
  10. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
  11. Let minutes be ? Get(input, "minutes").
  12. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
  13. Let months be ? Get(input, "months").
  14. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
  15. Let nanoseconds be ? Get(input, "nanoseconds").
  16. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
  17. Let seconds be ? Get(input, "seconds").
  18. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
  19. Let weeks be ? Get(input, "weeks").
  20. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
  21. Let years be ? Get(input, "years").
  22. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
  23. If years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are all undefined, throw a TypeError exception.
  24. If IsValidDurationRecord(result) is false, throw a RangeError exception.
  25. Return result.
+
  1. If Type(input) is not Object, then
    1. If Type(input) is String, throw a RangeError exception.
    2. Throw a TypeError exception.
  2. Let result be a new Duration Record with each field set to 0.
  3. Let days be ? Get(input, "days").
  4. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
  5. Let hours be ? Get(input, "hours").
  6. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
  7. Let microseconds be ? Get(input, "microseconds").
  8. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
  9. Let milliseconds be ? Get(input, "milliseconds").
  10. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
  11. Let minutes be ? Get(input, "minutes").
  12. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
  13. Let months be ? Get(input, "months").
  14. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
  15. Let nanoseconds be ? Get(input, "nanoseconds").
  16. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
  17. Let seconds be ? Get(input, "seconds").
  18. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
  19. Let weeks be ? Get(input, "weeks").
  20. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
  21. Let years be ? Get(input, "years").
  22. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
  23. If years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are all undefined, throw a TypeError exception.
  24. If IsValidDurationRecord(result) is false, throw a RangeError exception.
  25. Return result.
@@ -2631,12 +2802,12 @@

1.1.5 IsValidDurationRecord ( record

1.1.6 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours )

-

The abstract operation GetDurationUnitOptions takes arguments unit (a String), options (an Object), baseStyle (a String), stylesList (a List of Strings), digitalBase (a String), prevStyle (a String), and twoDigitHours (a Boolean) and returns either a normal completion containing a Record with [[Style]] and [[Display]] fields, or an abrupt completion. It extracts the relevant options for any given unit from an Object and returns them as a Record. It performs the following steps when called:

+

The abstract operation GetDurationUnitOptions takes arguments unit (a String), options (an Object), baseStyle (a String), stylesList (a List of Strings), digitalBase (a String), prevStyle (a String), and twoDigitHours (a Boolean) and returns either a normal completion containing a Record with [[Style]] and [[Display]] fields, or an abrupt completion. It extracts the relevant options for any given unit from an Object and returns them as a Record. It performs the following steps when called:

  1. Let style be ? GetOption(options, unit, string, stylesList, undefined).
  2. Let displayDefault be "always".
  3. If style is undefined, then
    1. If baseStyle is "digital", then
      1. If unit is not one of "hours", "minutes", or "seconds", then
        1. Set displayDefault to "auto".
      2. Set style to digitalBase.
    2. Else,
      1. If prevStyle is "fractional", "numeric" or "2-digit", then
        1. If unit is not one of "minutes" or "seconds", then
          1. Set displayDefault to "auto".
        2. Set style to "numeric".
      2. Else,
        1. Set displayDefault to "auto".
        2. Set style to baseStyle.
  4. If style is "numeric", then
    1. If unit is one of "milliseconds", "microseconds", or "nanoseconds", then
      1. Set style to "fractional".
      2. Set displayDefault to "auto".
  5. Let displayField be the string-concatenation of unit and "Display".
  6. Let display be ? GetOption(options, displayField, string, « "auto", "always" », displayDefault).
  7. If display is "always" and style is "fractional", then
    1. Throw a RangeError exception.
  8. If prevStyle is "fractional", then
    1. If style is not "fractional", then
      1. Throw a RangeError exception.
  9. If prevStyle is "numeric" or "2-digit", then
    1. If style is not "fractional", "numeric" or "2-digit", then
      1. Throw a RangeError exception.
    2. If unit is "minutes" or "seconds", then
      1. Set style to "2-digit".
  10. If unit is "hours" and twoDigitHours is true, then
    1. Set style to "2-digit".
  11. Return the Record { - [[Style]]: style, - [[Display]]: display - }.
+ [[Style]]: style, + [[Display]]: display + }.
@@ -2650,48 +2821,48 @@

1.1.7 AddFractionalDigits ( durationFormat<

1.1.8 NextUnitFractional ( durationFormat, unit )

The abstract operation NextUnitFractional takes arguments durationFormat (a DurationFormat Object) and unit (a String) and returns a Boolean. It returns true if the next smallest unit uses the "fractional" style. It performs the following steps when called:

-
  1. Assert: unit is "seconds", "milliseconds", or "microseconds".
  2. If unit is "seconds", then
    1. If durationFormat.[[MillisecondsStyle]] is "fractional", return true.
  3. If unit is "milliseconds", then
    1. If durationFormat.[[MicrosecondsStyle]] is "fractional", return true.
  4. If unit is "microseconds", then
    1. If durationFormat.[[NanosecondsStyle]] is "fractional", return true.
  5. Return false.
+
  1. Assert: unit is "seconds", "milliseconds", or "microseconds".
  2. If unit is "seconds", then
    1. If durationFormat.[[MillisecondsStyle]] is "fractional", return true.
  3. If unit is "milliseconds", then
    1. If durationFormat.[[MicrosecondsStyle]] is "fractional", return true.
  4. If unit is "microseconds", then
    1. If durationFormat.[[NanosecondsStyle]] is "fractional", return true.
  5. Return false.

1.1.9 FormatNumericHours ( locale, hoursStyle, hoursValue, signDisplayed )

The abstract operation FormatNumericHours takes arguments locale (a Unicode canonicalized locale identifier), hoursStyle (a String), hoursValue (an integer), and signDisplayed (a Boolean) and returns a List of Records. It creates a List of Records containing the formatted parts of the hours unit of duration when the requested style is "numeric" or "2-digit" according to the effective locale and the formatting options of durationFormat. It performs the following steps when called:

-
  1. Assert: hoursStyle is "numeric" or hoursStyle is "2-digit".
  2. Let nfOpts be OrdinaryObjectCreate(null).
  3. If hoursStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
  4. If signDisplayed is false, then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  5. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]] », nfOpts).
  6. Let hoursParts be ! PartitionNumberPattern(nf, hoursValue).
  7. For each Record { [[Type]], [[Value]] } part of hoursParts, do
    1. Return the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "hour" }.
+
  1. Assert: hoursStyle is "numeric" or hoursStyle is "2-digit".
  2. Let nfOpts be OrdinaryObjectCreate(null).
  3. If hoursStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
  4. If signDisplayed is false, then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  5. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]] », nfOpts).
  6. Let hoursParts be ! PartitionNumberPattern(nf, hoursValue).
  7. For each Record { [[Type]], [[Value]] } part of hoursParts, do
    1. Return the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "hour" }.

1.1.10 FormatNumericMinutes ( durationFormat, minutesValue, hoursDisplayed, signDisplayed )

The abstract operation FormatNumericMinutes takes arguments durationFormat (a DurationFormat Object), minutesValue (an integer), hoursDisplayed (a Boolean), and signDisplayed (a Boolean) and returns a List of Records. It creates a List of Records containing the formatted parts of the hours unit of duration when the requested style is "numeric" or "2-digit" according to the effective locale and the formatting options of durationFormat. It performs the following steps when called:

-
  1. Let result be a new empty List.
  2. If hoursDisplayed is true, then
    1. Let digitalFormat be durationFormat.[[DigitalFormat]].
    2. Let separator be digitalFormat.[[HoursMinutesSeparator]].
    3. Append the Record { [[Type]]: "literal", [[Value]]: separator, [[Unit]]: empty } to result.
  3. Let minutesStyle be durationFormat.[[MinutesStyle]].
  4. Assert: minutesStyle is "numeric" or minutesStyle is "2-digit".
  5. Let nfOpts be OrdinaryObjectCreate(null).
  6. If minutesStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
  7. If signDisplayed is false, then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  8. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]] », nfOpts).
  9. Let minutesParts be ! PartitionNumberPattern(nf, minutesValue).
  10. For each Record { [[Type]], [[Value]] } part of minutesParts, do
    1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "minute" } to result.
  11. Return result.
+
  1. Let result be a new empty List.
  2. If hoursDisplayed is true, then
    1. Let digitalFormat be durationFormat.[[DigitalFormat]].
    2. Let separator be digitalFormat.[[HoursMinutesSeparator]].
    3. Append the Record { [[Type]]: "literal", [[Value]]: separator, [[Unit]]: empty } to result.
  3. Let minutesStyle be durationFormat.[[MinutesStyle]].
  4. Assert: minutesStyle is "numeric" or minutesStyle is "2-digit".
  5. Let nfOpts be OrdinaryObjectCreate(null).
  6. If minutesStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
  7. If signDisplayed is false, then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  8. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]] », nfOpts).
  9. Let minutesParts be ! PartitionNumberPattern(nf, minutesValue).
  10. For each Record { [[Type]], [[Value]] } part of minutesParts, do
    1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "minute" } to result.
  11. Return result.

1.1.11 FormatNumericSeconds ( durationFormat, secondsValue, minutesDisplayed, signDisplayed )

The abstract operation FormatNumericSeconds takes arguments durationFormat (a DurationFormat Object), secondsValue (an integer), minutesDisplayed (a Boolean), and signDisplayed (a Boolean) and returns a List of Records. It creates a List of Records containing the formatted parts of the seconds unit of duration and all subsecond units when the requested style is "numeric" or "2-digit" according to the effective locale and the formatting options of durationFormat. It performs the following steps when called:

-
  1. Let result be a new empty List.
  2. If minutesDisplayed is true, then
    1. Let digitalFormat be durationFormat.[[DigitalFormat]].
    2. Let separator be digitalFormat.[[MinutesSecondsSeparator]].
    3. Append the Record { [[Type]]: "literal", [[Value]]: separator, [[Unit]]: empty } to result.
  3. Let nfOpts be OrdinaryObjectCreate(null).
  4. Let secondsStyle be durationFormat.[[SecondsStyle]].
  5. Assert: secondsStyle is "numeric" or secondsStyle is "2-digit".
  6. If secondsStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
    2. If signDisplayed is false, then
      1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  7. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »).
  8. Let fractionalDigits be AddFractionalDigits(durationFormat, _duration).
  9. If fractionalDigits is not 0, then
    1. If durationFormat.[[FractionalDigits]] is undefined, then
      1. Let maximumFractionDigits be 9𝔽.
      2. Let minimumFractionDigits be +0𝔽.
    2. Else,
      1. Let maximumFractionDigits be durationFormat.[[FractionalDigits]].
      2. Let minimumFractionDigits be durationFormat.[[FractionalDigits]].
    3. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits).
    4. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits).
    5. Perform ! CreateDataPropertyOrThrow(nfOpts, "roundingMode", "trunc").
  10. Let secondsParts be ! PartitionNumberPattern(nf, secondsValue).
  11. For each Record { [[Type]], [[Value]] } part of secondsParts, do
    1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "second" } to result.
  12. Return result.
+
  1. Let result be a new empty List.
  2. If minutesDisplayed is true, then
    1. Let digitalFormat be durationFormat.[[DigitalFormat]].
    2. Let separator be digitalFormat.[[MinutesSecondsSeparator]].
    3. Append the Record { [[Type]]: "literal", [[Value]]: separator, [[Unit]]: empty } to result.
  3. Let nfOpts be OrdinaryObjectCreate(null).
  4. Let secondsStyle be durationFormat.[[SecondsStyle]].
  5. Assert: secondsStyle is "numeric" or secondsStyle is "2-digit".
  6. If secondsStyle is "2-digit", then
    1. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumIntegerDigits", 2𝔽).
    2. If signDisplayed is false, then
      1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
  7. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »).
  8. Let fractionalDigits be AddFractionalDigits(durationFormat, _duration).
  9. If fractionalDigits is not 0, then
    1. If durationFormat.[[FractionalDigits]] is undefined, then
      1. Let maximumFractionDigits be 9𝔽.
      2. Let minimumFractionDigits be +0𝔽.
    2. Else,
      1. Let maximumFractionDigits be durationFormat.[[FractionalDigits]].
      2. Let minimumFractionDigits be durationFormat.[[FractionalDigits]].
    3. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits).
    4. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits).
    5. Perform ! CreateDataPropertyOrThrow(nfOpts, "roundingMode", "trunc").
  10. Let secondsParts be ! PartitionNumberPattern(nf, secondsValue).
  11. For each Record { [[Type]], [[Value]] } part of secondsParts, do
    1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: "second" } to result.
  12. Return result.

1.1.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed )

The abstract operation FormatNumericUnits takes arguments durationFormat (a DurationFormat Object), duration (a Duration Record), firstNumericUnit (a String), and signDisplayed (a Boolean) and returns a List of Records. It creates a List of Records containing the formatted parts of duration that use "numeric" or "2-digit" style according to the effective locale and the formatting options of durationFormat. It performs the following steps when called:

-
  1. Assert: firstNumericUnit is "hours", "minutes", or "seconds".
  2. Let numericPartsList be a new empty List.
  3. Let hoursValue be duration.[[Hours]].
  4. Let hoursDisplay be durationFormat.[[HoursDisplay]].
  5. Let secondsValue be duration.[[Seconds]].
  6. Set secondsValue to secondsValue + AddFractionalDigits(durationFormat, duration).
  7. Let minutesValue be duration.[[Minutes]].
  8. Let minutesDisplay be durationFormat.[[MinutesDisplay]].
  9. Let secondsDisplay be durationFormat.[[SecondsDisplay]].
  10. If hoursValue is not 0 or hoursDisplay is not "auto", then
    1. Let hoursFormatted be true.
  11. Else,
    1. Let hoursFormatted be false.
  12. If secondsValue is not 0 or secondsDisplay is not "auto", then
    1. Let secondsFormatted be true.
  13. Else,
    1. Let secondsFormatted be false.
  14. If hoursFormatted is true and secondsFormatted is true, then
    1. Let minutesFormatted be true.
  15. Else if minutesValue is not 0 or minutesDisplay is not "auto", then
    1. Let minutesFormatted be true.
  16. Else,
    1. Let minutesFormatted be false.
  17. If hoursFormatted is true, then
    1. Let hoursStyle be durationFormat.[[HoursStyle]].
    2. Let locale be durationFormat.[[Locale]].
    3. Append FormatNumericHours(locale, hoursStyle, hoursValue, signDisplayed) to numericPartsList.
    4. Set signDisplayed to false.
  18. If minutesFormatted is true, then
    1. Let minutesStyle be durationFormat.[[MinutesStyle]].
    2. Append FormatNumericMinutes(minutesValue, minutesStyle, hoursFormatted, signDisplayed) to numericPartsList.
    3. Set signDisplayed to false.
  19. If secondsFormatted is true, then
    1. Append FormatNumericSeconds(durationFormat, secondsValue, minutesFormatted, signDisplayed) to numericPartsList.
    2. Set signDisplayed to false.
  20. Return numericPartsList.
+
  1. Assert: firstNumericUnit is "hours", "minutes", or "seconds".
  2. Let numericPartsList be a new empty List.
  3. Let hoursValue be duration.[[Hours]].
  4. Let hoursDisplay be durationFormat.[[HoursDisplay]].
  5. Let secondsValue be duration.[[Seconds]].
  6. Set secondsValue to secondsValue + AddFractionalDigits(durationFormat, duration).
  7. Let minutesValue be duration.[[Minutes]].
  8. Let minutesDisplay be durationFormat.[[MinutesDisplay]].
  9. Let secondsDisplay be durationFormat.[[SecondsDisplay]].
  10. If hoursValue is not 0 or hoursDisplay is not "auto", then
    1. Let hoursFormatted be true.
  11. Else,
    1. Let hoursFormatted be false.
  12. If secondsValue is not 0 or secondsDisplay is not "auto", then
    1. Let secondsFormatted be true.
  13. Else,
    1. Let secondsFormatted be false.
  14. If hoursFormatted is true and secondsFormatted is true, then
    1. Let minutesFormatted be true.
  15. Else if minutesValue is not 0 or minutesDisplay is not "auto", then
    1. Let minutesFormatted be true.
  16. Else,
    1. Let minutesFormatted be false.
  17. If hoursFormatted is true, then
    1. Let hoursStyle be durationFormat.[[HoursStyle]].
    2. Let locale be durationFormat.[[Locale]].
    3. Append FormatNumericHours(locale, hoursStyle, hoursValue, signDisplayed) to numericPartsList.
    4. Set signDisplayed to false.
  18. If minutesFormatted is true, then
    1. Let minutesStyle be durationFormat.[[MinutesStyle]].
    2. Append FormatNumericMinutes(minutesValue, minutesStyle, hoursFormatted, signDisplayed) to numericPartsList.
    3. Set signDisplayed to false.
  19. If secondsFormatted is true, then
    1. Append FormatNumericSeconds(durationFormat, secondsValue, minutesFormatted, signDisplayed) to numericPartsList.
    2. Set signDisplayed to false.
  20. Return numericPartsList.

1.1.13 ListFormatParts ( durationFormat, nfResult )

The abstract operation ListFormatParts takes arguments durationFormat (a DurationFormat Object) and nfResult (a List of Records) and returns a List. It creates and returns a List with all the corresponding parts as formatted by ListFormat. It performs the following steps when called:

-
  1. Let lfOpts be OrdinaryObjectCreate(null).
  2. Perform ! CreateDataPropertyOrThrow(lfOpts, "type", "unit").
  3. Let listStyle be durationFormat.[[Style]].
  4. If listStyle is "digital", then
    1. Set listStyle to "short".
  5. Perform ! CreateDataPropertyOrThrow(lfOpts, "style", listStyle).
  6. Let lf be ! Construct(%ListFormat%, « durationFormat.[[Locale]], lfOpts »).
  7. Let strings be a new empty List.
  8. For each element parts of nfResult, do
    1. Let string be the empty String.
    2. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Set string to the string-concatenation of string and part.[[Value]].
    3. Append string to strings.
  9. Let formatted be CreatePartsFromList(lf, strings).
  10. Let nfResultIndex be 0.
  11. Let nfResultLength be the number of elements in nfResult.
  12. Let flattened be a new empty List.
  13. For each Record { [[Type]], [[Value]] } listPart in formatted, do
    1. If listPart.[[Type]] is "element", then
      1. Assert: nfResultIndex < nfResultLength.
      2. Let parts be nfResult[nfResultIndex].
      3. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
        1. Append part to flattened.
      4. Set nfResultIndex to nfResultIndex + 1.
    2. Else,
      1. Assert: listPart.[[Type]] is "literal".
      2. Append the Record { [[Type]]: "literal", [[Value]]: listPart.[[Value]], [[Unit]]: empty } to flattened.
  14. Return flattened.
+
  1. Let lfOpts be OrdinaryObjectCreate(null).
  2. Perform ! CreateDataPropertyOrThrow(lfOpts, "type", "unit").
  3. Let listStyle be durationFormat.[[Style]].
  4. If listStyle is "digital", then
    1. Set listStyle to "short".
  5. Perform ! CreateDataPropertyOrThrow(lfOpts, "style", listStyle).
  6. Let lf be ! Construct(%ListFormat%, « durationFormat.[[Locale]], lfOpts »).
  7. Let strings be a new empty List.
  8. For each element parts of nfResult, do
    1. Let string be the empty String.
    2. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Set string to the string-concatenation of string and part.[[Value]].
    3. Append string to strings.
  9. Let formatted be CreatePartsFromList(lf, strings).
  10. Let nfResultIndex be 0.
  11. Let nfResultLength be the number of elements in nfResult.
  12. Let flattened be a new empty List.
  13. For each Record { [[Type]], [[Value]] } listPart in formatted, do
    1. If listPart.[[Type]] is "element", then
      1. Assert: nfResultIndex < nfResultLength.
      2. Let parts be nfResult[nfResultIndex].
      3. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
        1. Append part to flattened.
      4. Set nfResultIndex to nfResultIndex + 1.
    2. Else,
      1. Assert: listPart.[[Type]] is "literal".
      2. Append the Record { [[Type]]: "literal", [[Value]]: listPart.[[Value]], [[Unit]]: empty } to flattened.
  14. Return flattened.

1.1.14 PartitionDurationFormatPattern ( durationFormat, duration )

The abstract operation PartitionDurationFormatPattern takes arguments durationFormat (a DurationFormat) and duration (a Duration Record) and returns a List. It creates and returns a List with all the corresponding parts according to the effective locale and the formatting options of durationFormat. It performs the following steps when called:

-
  1. Let result be a new empty List.
  2. Let signDisplayed be true.
  3. Let fractionalUnitFound be false.
  4. While fractionalUnitFound is false, repeat for each row in Table 2 in table order, except the header row:
    1. Let value be the value of duration's field whose name is the Value Field of the current row.
    2. Let style be the value of durationFormat's internal slot whose name is the Style Slot value of the current row.
    3. Let display be the value of durationFormat's internal slot whose name is the Display Slot value of the current row.
    4. Let unit be the Unit value of the current row.
    5. If style is "numeric" or "2-digit", then
      1. Append FormatNumericUnits(durationFormat, duration, unit, signDisplayed) to result.
      2. Return result.
    6. Let nfOpts be OrdinaryObjectCreate(null).
    7. If unit is "seconds", "milliseconds", or "microseconds", then
      1. If NextUnitFractional(durationFormat, unit) is true, then
        1. Set value to value + AddFractionalDigits(durationFormat, duration).
        2. If durationFormat.[[FractionalDigits]] is undefined, then
          1. Let maximumFractionDigits be 9𝔽.
          2. Let minimumFractionDigits be +0𝔽.
        3. Else,
          1. Let maximumFractionDigits be durationFormat.[[FractionalDigits]].
          2. Let minimumFractionDigits be durationFormat.[[FractionalDigits]].
        4. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits).
        5. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits).
        6. Perform ! CreateDataPropertyOrThrow(nfOpts, "roundingMode", "trunc").
        7. Set fractionalUnitFound to true.
      2. If value is not 0 or display is not "auto", then
        1. Let numberingSystem be durationFormat.[[NumberingSystem]].
        2. Perform ! CreateDataPropertyOrThrow(nfOpts, "numberingSystem", numberingSystem).
        3. If signDisplayed is true, then
          1. Set signDisplayed to false.
          2. If value is 0 and DurationRecordSign(duration) is -1, then
            1. Set value to negative-zero.
        4. Else,
          1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
        5. Let numberFormatUnit be the NumberFormat Unit value of the current row.
        6. Perform ! CreateDataPropertyOrThrow(nfOpts, "style", "unit").
        7. Perform ! CreateDataPropertyOrThrow(nfOpts, "unit", numberFormatUnit).
        8. Perform ! CreateDataPropertyOrThrow(nfOpts, "unitDisplay", style).
        9. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »).
        10. Let parts be ! PartitionNumberPattern(nf, value).
        11. Let list be a new empty List.
        12. For each Record { [[Type]], [[Value]] } part of parts, do
          1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part[[Value]], [[Unit]]: numberFormatUnit } to list.
        13. Append list to result.
  5. Return ListFormatParts(durationFormat, result).
+
  1. Let result be a new empty List.
  2. Let signDisplayed be true.
  3. Let fractionalUnitFound be false.
  4. While fractionalUnitFound is false, repeat for each row in Table 2 in table order, except the header row:
    1. Let value be the value of duration's field whose name is the Value Field of the current row.
    2. Let style be the value of durationFormat's internal slot whose name is the Style Slot value of the current row.
    3. Let display be the value of durationFormat's internal slot whose name is the Display Slot value of the current row.
    4. Let unit be the Unit value of the current row.
    5. If style is "numeric" or "2-digit", then
      1. Append FormatNumericUnits(durationFormat, duration, unit, signDisplayed) to result.
      2. Return result.
    6. Let nfOpts be OrdinaryObjectCreate(null).
    7. If unit is "seconds", "milliseconds", or "microseconds", then
      1. If NextUnitFractional(durationFormat, unit) is true, then
        1. Set value to value + AddFractionalDigits(durationFormat, duration).
        2. If durationFormat.[[FractionalDigits]] is undefined, then
          1. Let maximumFractionDigits be 9𝔽.
          2. Let minimumFractionDigits be +0𝔽.
        3. Else,
          1. Let maximumFractionDigits be durationFormat.[[FractionalDigits]].
          2. Let minimumFractionDigits be durationFormat.[[FractionalDigits]].
        4. Perform ! CreateDataPropertyOrThrow(nfOpts, "maximumFractionDigits", maximumFractionDigits).
        5. Perform ! CreateDataPropertyOrThrow(nfOpts, "minimumFractionDigits", minimumFractionDigits).
        6. Perform ! CreateDataPropertyOrThrow(nfOpts, "roundingMode", "trunc").
        7. Set fractionalUnitFound to true.
      2. If value is not 0 or display is not "auto", then
        1. Let numberingSystem be durationFormat.[[NumberingSystem]].
        2. Perform ! CreateDataPropertyOrThrow(nfOpts, "numberingSystem", numberingSystem).
        3. If signDisplayed is true, then
          1. Set signDisplayed to false.
          2. If value is 0 and DurationRecordSign(duration) is -1, then
            1. Set value to negative-zero.
        4. Else,
          1. Perform ! CreateDataPropertyOrThrow(nfOpts, "signDisplay", "never").
        5. Let numberFormatUnit be the NumberFormat Unit value of the current row.
        6. Perform ! CreateDataPropertyOrThrow(nfOpts, "style", "unit").
        7. Perform ! CreateDataPropertyOrThrow(nfOpts, "unit", numberFormatUnit).
        8. Perform ! CreateDataPropertyOrThrow(nfOpts, "unitDisplay", style).
        9. Let nf be ! Construct(%NumberFormat%, « durationFormat.[[Locale]], nfOpts »).
        10. Let parts be ! PartitionNumberPattern(nf, value).
        11. Let list be a new empty List.
        12. For each Record { [[Type]], [[Value]] } part of parts, do
          1. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part[[Value]], [[Unit]]: numberFormatUnit } to list.
        13. Append list to result.
  5. Return ListFormatParts(durationFormat, result).
Table 2: DurationFormat instance internal slots and properties relevant to PartitionDurationFormatPattern
@@ -2706,72 +2877,72 @@

1.1.14 PartitionDurationFormatPattern ( dur - [[Years]] - [[YearsStyle]] - [[YearsDisplay]] + [[Years]] + [[YearsStyle]] + [[YearsDisplay]] "years" "year" - [[Months]] - [[MonthsStyle]] - [[MonthsDisplay]] + [[Months]] + [[MonthsStyle]] + [[MonthsDisplay]] "months" "month" - [[Weeks]] - [[WeeksStyle]] - [[WeeksDisplay]] + [[Weeks]] + [[WeeksStyle]] + [[WeeksDisplay]] "weeks" "week" - [[Days]] - [[DaysStyle]] - [[DaysDisplay]] + [[Days]] + [[DaysStyle]] + [[DaysDisplay]] "days" "day" - [[Hours]] - [[HoursStyle]] - [[HoursDisplay]] + [[Hours]] + [[HoursStyle]] + [[HoursDisplay]] "hours" "hour" - [[Minutes]] - [[MinutesStyle]] - [[MinutesDisplay]] + [[Minutes]] + [[MinutesStyle]] + [[MinutesDisplay]] "minutes" "minute" - [[Seconds]] - [[SecondsStyle]] - [[SecondsDisplay]] + [[Seconds]] + [[SecondsStyle]] + [[SecondsDisplay]] "seconds" "second" - [[Milliseconds]] - [[MillisecondsStyle]] - [[MillisecondsDisplay]] + [[Milliseconds]] + [[MillisecondsStyle]] + [[MillisecondsDisplay]] "milliseconds" "millisecond" - [[Microseconds]] - [[MicrosecondsStyle]] - [[MicrosecondsDisplay]] + [[Microseconds]] + [[MicrosecondsStyle]] + [[MicrosecondsDisplay]] "microseconds" "microsecond" - [[Nanoseconds]] - [[NanosecondsStyle]] - [[NanosecondsDisplay]] + [[Nanoseconds]] + [[NanosecondsStyle]] + [[NanosecondsDisplay]] "nanoseconds" "nanosecond" @@ -2790,7 +2961,7 @@

1.2.1 Intl.DurationFormat ( [ locales

When the Intl.DurationFormat function is called with optional arguments locales and options, the following steps are taken:

-
  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let durationFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%DurationFormatPrototype%", « [[InitializedDurationFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[YearsStyle]], [[YearsDisplay]], [[MonthsStyle]], [[MonthsDisplay]], [[WeeksStyle]], [[WeeksDisplay]], [[DaysStyle]], [[DaysDisplay]], [[HoursStyle]], [[HoursDisplay]], [[MinutesStyle]], [[MinutesDisplay]], [[SecondsStyle]], [[SecondsDisplay]], [[MillisecondsStyle]], [[MillisecondsDisplay]], [[MicrosecondsStyle]], [[MicrosecondsDisplay]], [[NanosecondsStyle]], [[NanosecondsDisplay]], [[HoursMinutesSeparator]], [[MinutesSecondsSeparator]], [[FractionalDigits]], [[TwoDigitHours]] »).
  3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  4. Let options be ? GetOptionsObject(options).
  5. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
  6. Let numberingSystem be ? GetOption(options, "numberingSystem", string, undefined, undefined).
  7. If numberingSystem is not undefined, then
    1. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
  8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }.
  9. Let r be ResolveLocale(%DurationFormat%.[[AvailableLocales]], requestedLocales, opt, %DurationFormat%.[[RelevantExtensionKeys]], %DurationFormat%.[[LocaleData]]).
  10. Let locale be r.[[locale]].
  11. Set durationFormat.[[Locale]] to locale.
  12. Set durationFormat.[[DataLocale]] to r.[[dataLocale]].
  13. Let dataLocale be durationFormat.[[DataLocale]].
  14. Let dataLocaleData be durationFormat.[[LocaleData]].[[<dataLocale>]].
  15. Let digitalFormat be dataLocaleData.[[DigitalFormat]].
  16. Let twoDigitHours be digitalFormat.[[TwoDigitHours]].
  17. Set durationFormat.[[TwoDigitHours]] to twoDigitHours.
  18. Let hoursMinutesSeparator be digitalFormat.[[HoursMinutesSeparator]].
  19. Set durationFormat.[[HoursMinutesSeparator]] to hoursMinutesSeparator.
  20. Let minutesSecondsSeparator be digitalFormat.[[MinutesSecondsSeparator]].
  21. Set durationFormat.[[MinutesSecondsSeparator]] to minutesSecondsSeparator.
  22. Set durationFormat.[[NumberingSystem]] to r.[[nu]].
  23. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow", "digital" », "short").
  24. Set durationFormat.[[Style]] to style.
  25. Let prevStyle be the empty String.
  26. For each row of Table 3, except the header row, in table order, do
    1. Let styleSlot be the Style Slot value of the current row.
    2. Let displaySlot be the Display Slot value of the current row.
    3. Let unit be the Unit value of the current row.
    4. Let valueList be the Values value of the current row.
    5. Let digitalBase be the Digital Default value of the current row.
    6. Let unitOptions be ? GetDurationUnitOptions(unit, options, style, valueList, digitalBase, prevStyle, twoDigitHours).
    7. Set the value of the styleSlot slot of durationFormat to unitOptions.[[Style]].
    8. Set the value of the displaySlot slot of durationFormat to unitOptions.[[Display]].
    9. If unit is one of "hours", "minutes", "seconds", "milliseconds", or "microseconds", then
      1. Set prevStyle to unitOptions.[[Style]].
  27. Set durationFormat.[[FractionalDigits]] to ? GetNumberOption(options, "fractionalDigits", 0, 9, undefined).
  28. Return durationFormat.
+
  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let durationFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%DurationFormatPrototype%", « [[InitializedDurationFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[YearsStyle]], [[YearsDisplay]], [[MonthsStyle]], [[MonthsDisplay]], [[WeeksStyle]], [[WeeksDisplay]], [[DaysStyle]], [[DaysDisplay]], [[HoursStyle]], [[HoursDisplay]], [[MinutesStyle]], [[MinutesDisplay]], [[SecondsStyle]], [[SecondsDisplay]], [[MillisecondsStyle]], [[MillisecondsDisplay]], [[MicrosecondsStyle]], [[MicrosecondsDisplay]], [[NanosecondsStyle]], [[NanosecondsDisplay]], [[HoursMinutesSeparator]], [[MinutesSecondsSeparator]], [[FractionalDigits]], [[TwoDigitHours]] »).
  3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  4. Let options be ? GetOptionsObject(options).
  5. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
  6. Let numberingSystem be ? GetOption(options, "numberingSystem", string, undefined, undefined).
  7. If numberingSystem is not undefined, then
    1. If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
  8. Let opt be the Record { [[localeMatcher]]: matcher, [[nu]]: numberingSystem }.
  9. Let r be ResolveLocale(%DurationFormat%.[[AvailableLocales]], requestedLocales, opt, %DurationFormat%.[[RelevantExtensionKeys]], %DurationFormat%.[[LocaleData]]).
  10. Let locale be r.[[locale]].
  11. Set durationFormat.[[Locale]] to locale.
  12. Set durationFormat.[[DataLocale]] to r.[[dataLocale]].
  13. Let dataLocale be durationFormat.[[DataLocale]].
  14. Let dataLocaleData be durationFormat.[[LocaleData]].[[<dataLocale>]].
  15. Let digitalFormat be dataLocaleData.[[DigitalFormat]].
  16. Let twoDigitHours be digitalFormat.[[TwoDigitHours]].
  17. Set durationFormat.[[TwoDigitHours]] to twoDigitHours.
  18. Let hoursMinutesSeparator be digitalFormat.[[HoursMinutesSeparator]].
  19. Set durationFormat.[[HoursMinutesSeparator]] to hoursMinutesSeparator.
  20. Let minutesSecondsSeparator be digitalFormat.[[MinutesSecondsSeparator]].
  21. Set durationFormat.[[MinutesSecondsSeparator]] to minutesSecondsSeparator.
  22. Set durationFormat.[[NumberingSystem]] to r.[[nu]].
  23. Let style be ? GetOption(options, "style", string, « "long", "short", "narrow", "digital" », "short").
  24. Set durationFormat.[[Style]] to style.
  25. Let prevStyle be the empty String.
  26. For each row of Table 3, except the header row, in table order, do
    1. Let styleSlot be the Style Slot value of the current row.
    2. Let displaySlot be the Display Slot value of the current row.
    3. Let unit be the Unit value of the current row.
    4. Let valueList be the Values value of the current row.
    5. Let digitalBase be the Digital Default value of the current row.
    6. Let unitOptions be ? GetDurationUnitOptions(unit, options, style, valueList, digitalBase, prevStyle, twoDigitHours).
    7. Set the value of the styleSlot slot of durationFormat to unitOptions.[[Style]].
    8. Set the value of the displaySlot slot of durationFormat to unitOptions.[[Display]].
    9. If unit is one of "hours", "minutes", "seconds", "milliseconds", or "microseconds", then
      1. Set prevStyle to unitOptions.[[Style]].
  27. Set durationFormat.[[FractionalDigits]] to ? GetNumberOption(options, "fractionalDigits", 0, 9, undefined).
  28. Return durationFormat.
Table 3: Internal slots and property names of DurationFormat instances relevant to Intl.DurationFormat constructor
@@ -2804,71 +2975,71 @@

1.2.1 Intl.DurationFormat ( [ locales

- - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -2888,7 +3059,7 @@

1.3.1 Intl.DurationFormat.prototype

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

-

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

+

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

@@ -2896,24 +3067,24 @@

1.3.2 Intl.DurationFormat.supportedLocalesOf ( <

When the supportedLocalesOf method is called with arguments locales and options, the following steps are taken:

-
  1. Let availableLocales be %DurationFormat%.[[AvailableLocales]].
  2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
+
  1. Let availableLocales be %DurationFormat%.[[AvailableLocales]].
  2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  3. Return ? SupportedLocales(availableLocales, requestedLocales, options).

1.3.3 Internal slots

-

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

+

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

-

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

+

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

-

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

+

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

    -
  • [[LocaleData]].[[<locale>]].[[nu]] must be a List as specified in 12.3.3.
  • -
  • [[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: -
    • [[HourMinutesSeparator]] 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
    • -
    • [[MinutesSecondsSeparator]] 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.
    • -
    • [[TwoDigitHours]] is a Boolean value indicating whether hours are always displayed using two digits when the "numeric" style is used.
    • +
    • [[LocaleData]].[[<locale>]].[[nu]] must be a List as specified in 12.3.3.
    • +
    • [[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: +
      • [[HourMinutesSeparator]] 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
      • +
      • [[MinutesSecondsSeparator]] 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.
      • +
      • [[TwoDigitHours]] is a Boolean value indicating whether hours are always displayed using two digits when the "numeric" style is used.
    @@ -2925,7 +3096,7 @@

    1.3.3 Internal slots

    1.4 Properties of the Intl.DurationFormat Prototype Object

    -

    The Intl.DurationFormat prototype object is itself an ordinary object. %DurationFormatPrototype% 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.

    +

    The Intl.DurationFormat prototype object is itself an ordinary object. %DurationFormatPrototype% 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.

    1.4.1 Intl.DurationFormat.prototype.constructor

    @@ -2937,7 +3108,7 @@

    1.4.1 Intl.DurationFormat.prototype.constructor<

    1.4.2 Intl.DurationFormat.prototype [ @@toStringTag ]

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

    -

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

    +

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

    @@ -2945,21 +3116,21 @@

    1.4.3 Intl.DurationFormat.prototype.format ( When the format method is called with an argument duration, the following steps are taken:

    -
    1. Let df be this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let record be ? ToDurationRecord(duration).
    4. Let parts be PartitionDurationFormatPattern(df, record).
    5. Let result be the empty String.
    6. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Set result to the string-concatenation of result and part.[[Value]].
    7. Return result.
    +
    1. Let df be this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let record be ? ToDurationRecord(duration).
    4. Let parts be PartitionDurationFormatPattern(df, record).
    5. Let result be the empty String.
    6. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Set result to the string-concatenation of result and part.[[Value]].
    7. Return result.

    1.4.4 Intl.DurationFormat.prototype.formatToParts ( duration )

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

    -
    1. Let df be this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let record be ? ToDurationRecord(duration).
    4. Let parts be PartitionDurationFormatPattern(df, record).
    5. Let result be ! ArrayCreate(0).
    6. Let n be 0.
    7. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Let obj be OrdinaryObjectCreate(%ObjectPrototype%).
      2. Perform ! CreateDataPropertyOrThrow(obj, "type", part.[[Type]]).
      3. Perform ! CreateDataPropertyOrThrow(obj, "value", part.[[Value]]).
      4. If part.[[Unit]] is not empty, perform ! CreateDataPropertyOrThrow(obj, "unit", part.[[Unit]]).
      5. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), obj).
      6. Set n to n + 1.
    8. Return result.
    +
    1. Let df be this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let record be ? ToDurationRecord(duration).
    4. Let parts be PartitionDurationFormatPattern(df, record).
    5. Let result be ! ArrayCreate(0).
    6. Let n be 0.
    7. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
      1. Let obj be OrdinaryObjectCreate(%ObjectPrototype%).
      2. Perform ! CreateDataPropertyOrThrow(obj, "type", part.[[Type]]).
      3. Perform ! CreateDataPropertyOrThrow(obj, "value", part.[[Value]]).
      4. If part.[[Unit]] is not empty, perform ! CreateDataPropertyOrThrow(obj, "unit", part.[[Unit]]).
      5. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), obj).
      6. Set n to n + 1.
    8. Return result.

    1.4.5 Intl.DurationFormat.prototype.resolvedOptions ( )

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

    -
    1. Let df be the this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let options be OrdinaryObjectCreate(%ObjectPrototype%).
    4. For each row of Table 4, except the header row, in table order, do
      1. Let p be the Property value of the current row.
      2. Let v be the value of df's internal slot whose name is the Internal Slot value of the current row.
      3. If p is "fractionalDigits", then
        1. If v is not undefined, set v to 𝔽(v).
      4. Else,
        1. Assert: v is not undefined.
      5. If v is "fractional", then
        1. Assert: The Internal Slot value of the current row is [[MillisecondsStyle]], [[MicrosecondsStyle]], or [[NanosecondsStyle]] .
        2. Set v to "numeric".
      6. If v is not undefined, then
        1. Perform ! CreateDataPropertyOrThrow(options, p, v).
    5. Return options.
    +
    1. Let df be the this value.
    2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
    3. Let options be OrdinaryObjectCreate(%ObjectPrototype%).
    4. For each row of Table 4, except the header row, in table order, do
      1. Let p be the Property value of the current row.
      2. Let v be the value of df's internal slot whose name is the Internal Slot value of the current row.
      3. If p is "fractionalDigits", then
        1. If v is not undefined, set v to 𝔽(v).
      4. Else,
        1. Assert: v is not undefined.
      5. If v is "fractional", then
        1. Assert: The Internal Slot value of the current row is [[MillisecondsStyle]], [[MicrosecondsStyle]], or [[NanosecondsStyle]] .
        2. Set v to "numeric".
      6. If v is not undefined, then
        1. Perform ! CreateDataPropertyOrThrow(options, p, v).
    5. Return options.
    Table 4: Resolved Options of DurationFormat Instances
    @@ -2971,99 +3142,99 @@

    1.4.5 Intl.DurationFormat.prototype.resolvedOpti

- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
[[YearsStyle]][[YearsDisplay]][[YearsStyle]][[YearsDisplay]] "years" « "long", "short", "narrow" » "short"
[[MonthsStyle]][[MonthsDisplay]][[MonthsStyle]][[MonthsDisplay]] "months" « "long", "short", "narrow" » "short"
[[WeeksStyle]][[WeeksDisplay]][[WeeksStyle]][[WeeksDisplay]] "weeks" « "long", "short", "narrow" » "short"
[[DaysStyle]][[DaysDisplay]][[DaysStyle]][[DaysDisplay]] "days" « "long", "short", "narrow" » "short"
[[HoursStyle]][[HoursDisplay]][[HoursStyle]][[HoursDisplay]] "hours" « "long", "short", "narrow",
"numeric", "2-digit" »
"numeric"
[[MinutesStyle]][[MinutesDisplay]][[MinutesStyle]][[MinutesDisplay]] "minutes" « "long", "short", "narrow",
"numeric", "2-digit" »
"numeric"
[[SecondsStyle]][[SecondsDisplay]][[SecondsStyle]][[SecondsDisplay]] "seconds" « "long", "short", "narrow",
"numeric", "2-digit" »
"numeric"
[[MillisecondsStyle]][[MillisecondsDisplay]][[MillisecondsStyle]][[MillisecondsDisplay]] "milliseconds" « "long", "short", "narrow",
"fractional" »
"numeric"
[[MicrosecondsStyle]][[MicrosecondsDisplay]][[MicrosecondsStyle]][[MicrosecondsDisplay]] "microseconds" « "long", "short", "narrow",
"fractional" »
"fractional"
[[NanosecondsStyle]][[NanosecondsDisplay]][[NanosecondsStyle]][[NanosecondsDisplay]] "nanoseconds" « "long", "short", "narrow",
"fractional" »
"fractional"
[[Locale]][[Locale]] "locale"
[[NumberingSystem]][[NumberingSystem]] "numberingSystem"
[[Style]][[Style]] "style"
[[YearsStyle]][[YearsStyle]] "years"
[[YearsDisplay]][[YearsDisplay]] "yearsDisplay"
[[MonthsStyle]][[MonthsStyle]] "months"
[[MonthsDisplay]][[MonthsDisplay]] "monthsDisplay"
[[WeeksStyle]][[WeeksStyle]] "weeks"
[[WeeksDisplay]][[WeeksDisplay]] "weeksDisplay"
[[DaysStyle]][[DaysStyle]] "days"
[[DaysDisplay]][[DaysDisplay]] "daysDisplay"
[[HoursStyle]][[HoursStyle]] "hours"
[[HoursDisplay]][[HoursDisplay]] "hoursDisplay"
[[MinutesStyle]][[MinutesStyle]] "minutes"
[[MinutesDisplay]][[MinutesDisplay]] "minutesDisplay"
[[SecondsStyle]][[SecondsStyle]] "seconds"
[[SecondsDisplay]][[SecondsDisplay]] "secondsDisplay"
[[MillisecondsStyle]][[MillisecondsStyle]] "milliseconds"
[[MillisecondsDisplay]][[MillisecondsDisplay]] "millisecondsDisplay"
[[MicrosecondsStyle]][[MicrosecondsStyle]] "microseconds"
[[MicrosecondsDisplay]][[MicrosecondsDisplay]] "microsecondsDisplay"
[[NanosecondsStyle]][[NanosecondsStyle]] "nanoseconds"
[[NanosecondsDisplay]][[NanosecondsDisplay]] "nanosecondsDisplay"
[[FractionalDigits]][[FractionalDigits]] "fractionalDigits"
@@ -3075,35 +3246,35 @@

1.4.5 Intl.DurationFormat.prototype.resolvedOpti

1.5 Properties of Intl.DurationFormat Instances

Intl.DurationFormat instances inherit properties from %DurationFormatPrototype%.

-

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

+

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

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

    -
  • [[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
  • -
  • [[DataLocale]] is a String value with the language tag of the nearest locale for which the implementation has data to perform the formatting operation. It will be a parent locale of [[Locale]].
  • -
  • [[NumberingSystem]] is a String value with the "type" given in Unicode Technical Standard 35 for the numbering system used for formatting.
  • -
  • [[Style]] is one of the String values "long", "short", "narrow", or "digital" identifying the duration formatting style used.
  • -
  • [[YearsStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the years field.
  • -
  • [[YearsDisplay]] is one of the String values "auto" or "always" identifying when to display the years field.
  • -
  • [[MonthsStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the months field.
  • -
  • [[MonthsDisplay]] is one of the String values "auto" or "always" identifying when to display the months field.
  • -
  • [[WeeksStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the weeks field.
  • -
  • [[WeeksDisplay]] is one of the String values "auto" or "always" identifying when to display the weeks field.
  • -
  • [[DaysStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the days field.
  • -
  • [[DaysDisplay]] is one of the String values "auto" or "always" identifying when to display the days field.
  • -
  • [[HoursStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the hours field.
  • -
  • [[HoursDisplay]] is one of the String values "auto" or "always" identifying when to display the hours field.
  • -
  • [[MinutesStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the minutes field.
  • -
  • [[MinutesDisplay]] is one of the String values "auto" or "always" identifying when to display the minutes field.
  • -
  • [[SecondsStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the seconds field.
  • -
  • [[SecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the seconds field.
  • -
  • [[MillisecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the milliseconds field.
  • -
  • [[MillisecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the milliseconds field.
  • -
  • [[MicrosecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the microseconds field.
  • -
  • [[MicrosecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the microseconds field.
  • -
  • [[NanosecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the nanoseconds field.
  • -
  • [[NanosecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the nanoseconds field.
  • -
  • [[FractionalDigits]] is a non-negative integer, identifying the number of fractional digits to be used with numeric styles, or is undefined.
  • +
  • [[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
  • +
  • [[DataLocale]] is a String value with the language tag of the nearest locale for which the implementation has data to perform the formatting operation. It will be a parent locale of [[Locale]].
  • +
  • [[NumberingSystem]] is a String value with the "type" given in Unicode Technical Standard 35 for the numbering system used for formatting.
  • +
  • [[Style]] is one of the String values "long", "short", "narrow", or "digital" identifying the duration formatting style used.
  • +
  • [[YearsStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the years field.
  • +
  • [[YearsDisplay]] is one of the String values "auto" or "always" identifying when to display the years field.
  • +
  • [[MonthsStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the months field.
  • +
  • [[MonthsDisplay]] is one of the String values "auto" or "always" identifying when to display the months field.
  • +
  • [[WeeksStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the weeks field.
  • +
  • [[WeeksDisplay]] is one of the String values "auto" or "always" identifying when to display the weeks field.
  • +
  • [[DaysStyle]] is one of the String values "long", "short", or "narrow" identifying the formatting style used for the days field.
  • +
  • [[DaysDisplay]] is one of the String values "auto" or "always" identifying when to display the days field.
  • +
  • [[HoursStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the hours field.
  • +
  • [[HoursDisplay]] is one of the String values "auto" or "always" identifying when to display the hours field.
  • +
  • [[MinutesStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the minutes field.
  • +
  • [[MinutesDisplay]] is one of the String values "auto" or "always" identifying when to display the minutes field.
  • +
  • [[SecondsStyle]] is one of the String values "long", "short", "narrow", "2-digit", or "numeric" identifying the formatting style used for the seconds field.
  • +
  • [[SecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the seconds field.
  • +
  • [[MillisecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the milliseconds field.
  • +
  • [[MillisecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the milliseconds field.
  • +
  • [[MicrosecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the microseconds field.
  • +
  • [[MicrosecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the microseconds field.
  • +
  • [[NanosecondsStyle]] is one of the String values "long", "short", "narrow", or "fractional" identifying the formatting style used for the nanoseconds field.
  • +
  • [[NanosecondsDisplay]] is one of the String values "auto" or "always" identifying when to display the nanoseconds field.
  • +
  • [[FractionalDigits]] is a non-negative integer, identifying the number of fractional digits to be used with numeric styles, or is undefined.
@@ -3113,7 +3284,7 @@

Copyright Notice

© 2024 Ujjwal Sharma, Younies Mahmoud

Software License

-

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

+

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: