1NumberFormat Objects

1.1Abstract Operations For NumberFormat Objects

1.1.1SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation )

The abstract operation SetNumberFormatDigitOptions applies digit options used for number formatting onto the intl object.

  1. Assert: Type(intlObj) is Object.
  2. Assert: Type(options) is Object.
  3. Assert: Type(mnfdDefault) is Number.
  4. Assert: Type(mxfdDefault) is Number.
  5. Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1).
  6. Let mnfd be ? Get(options, "minimumFractionDigits").
  7. Let mxfd be ? Get(options, "maximumFractionDigits").
  8. Let mnsd be ? Get(options, "minimumSignificantDigits").
  9. Let mxsd be ? Get(options, "maximumSignificantDigits").
  10. Set intlObj.[[MinimumIntegerDigits]] to mnid.
  11. If mnsd is not undefined or mxsd is not undefined, then
    1. Set intlObj.[[RoundingType]] to significantDigits.
    2. Let mnsd be ? DefaultNumberOption(mnsd, 1, 21, 1).
    3. Let mxsd be ? DefaultNumberOption(mxsd, mnsd, 21, 21).
    4. Set intlObj.[[MinimumSignificantDigits]] to mnsd.
    5. Set intlObj.[[MaximumSignificantDigits]] to mxsd.
  12. Else if mnfd is not undefined or mxfd is not undefined, then
    1. Set intlObj.[[RoundingType]] to fractionDigits.
    2. Let mnfd be ? DefaultNumberOption(mnfd, 0, 20, mnfdDefault).
    3. Let mxfdActualDefault be max( mnfd, mxfdDefault ).
    4. Let mxfd be ? DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault).
    5. Set intlObj.[[MinimumFractionDigits]] to mnfd.
    6. Set intlObj.[[MaximumFractionDigits]] to mxfd.
  13. Else if notation is "compact", then
    1. Set intlObj.[[RoundingType]] to compactRounding.
  14. Else,
    1. Set intlObj.[[RoundingType]] to fractionDigits.
    2. Set intlObj.[[MinimumFractionDigits]] to mnfdDefault.
    3. Set intlObj.[[MaximumFractionDigits]] to mxfdDefault.

1.1.2InitializeNumberFormat ( numberFormat, locales, options )

The abstract operation InitializeNumberFormat accepts the arguments numberFormat (which must be an object), locales, and options. It initializes numberFormat as a NumberFormat object. The following steps are taken:

  1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  2. If options is undefined, then
    1. Let options be ObjectCreate(null).
  3. Else,
    1. Let options be ? ToObject(options).
  4. Let opt be a new Record.
  5. Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
  6. Set opt.[[localeMatcher]] to matcher.
  7. Let localeData be %NumberFormat%.[[LocaleData]].
  8. Let r be ResolveLocale(%NumberFormat%.[[AvailableLocales]], requestedLocales, opt, %NumberFormat%.[[RelevantExtensionKeys]], localeData).
  9. Set numberFormat.[[Locale]] to r.[[locale]].
  10. Set numberFormat.[[DataLocale]] to r.[[dataLocale]].
  11. Set numberFormat.[[NumberingSystem]] to r.[[nu]].
  12. Perform ? SetNumberFormatUnitOptions(numberFormat, options).
  13. Let style be numberFormat.[[Style]].
  14. If style is "currency", then
    1. Let currency be numberFormat.[[Currency]].
    2. Let cDigits be CurrencyDigits(currency).
    3. Let mnfdDefault be cDigits.
    4. Let mxfdDefault be cDigits.
  15. Else,
    1. Let mnfdDefault be 0.
    2. If style is "percent", then
      1. Let mxfdDefault be 0.
    3. Else,
      1. Let mxfdDefault be 3.
  16. Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
  17. Set numberFormat.[[Notation]] to notation.
  18. Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
  19. Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
  20. If notation is "compact", then
    1. Set numberFormat.[[CompactDisplay]] to compactDisplay.
  21. Let useGrouping be ? GetOption(options, "useGrouping", "boolean", undefined, true).
  22. Set numberFormat.[[UseGrouping]] to useGrouping.
  23. Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto").
  24. Set numberFormat.[[SignDisplay]] to signDisplay.
  25. Return numberFormat.

1.1.3CurrencyDigits ( currency )

When the CurrencyDigits abstract operation is called with an argument currency (which must be an upper case String value), the following steps are taken:

  1. If the ISO 4217 currency and funds code list contains currency as an alphabetic code, return the minor unit value corresponding to the currency from the list; otherwise, return 2.

1.1.4Number Format Functions

A Number format function is an anonymous built-in function that has a [[NumberFormat]] internal slot.

When a Number format function F is called with optional argument value, the following steps are taken:

  1. Let nf be F.[[NumberFormat]].
  2. Assert: Type(nf) is Object and nf has an [[InitializedNumberFormat]] internal slot.
  3. If value is not provided, let value be undefined.
  4. Let x be ? ToNumeric(value).
  5. Return ? FormatNumeric(nf, x).

The length property of a Number format function is 1.

1.1.5FormatNumericToString ( intlObject, x )

The FormatNumericToString abstract operation is called with arguments intlObject (which must be an object with [[RoundingType]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], and [[MaximumFractionDigits]] internal slots), and x (which must be a Number or BigInt value), and returns a Record containing two values: x as a String value with digits formatted according to the five formatting parameters in the field [[FormattedString]], and the final floating decimal value of x after rounding has been performed in the field [[RoundedNumber]].

  1. If x < 0 or x is -0, let isNegative be true; else let isNegative be false.
  2. If isNegative, then
    1. Let x be -x.
  3. If intlObject.[[RoundingType]] is significantDigits, then
    1. Let result be ToRawPrecision(x, intlObject.[[MinimumSignificantDigits]], intlObject.[[MaximumSignificantDigits]]).
  4. Else if intlObject.[[RoundingType]] is fractionDigits, then
    1. Let result be ToRawFixed(x, intlObject.[[MinimumFractionDigits]], intlObject.[[MaximumFractionDigits]]).
  5. Else,
    1. Assert: intlObject.[[RoundingType]] is compactRounding.
    2. Let result be ToRawPrecision(x, 1, 2).
    3. If result.[[IntegerDigitsCount]] > 1, then
      1. Let result be ToRawFixed(x, 0, 0).
  6. Let x be result.[[RoundedNumber]].
  7. Let string be result.[[FormattedString]].
  8. Let int be result.[[IntegerDigitsCount]].
  9. Let minInteger be intlObject.[[MinimumIntegerDigits]].
  10. If int < minInteger, then
    1. Let forwardZeros be the String consisting of minIntegerint occurrences of the character "0".
    2. Set string to the string-concatenation of forwardZeros and string.
  11. If isNegative, then
    1. Let x be -x.
  12. Return the Record { [[RoundedNumber]]: x, [[FormattedString]]: string }.

1.1.6PartitionNumberPattern ( numberFormat, x )

The PartitionNumberPattern abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat) and x (which must be a Number or BigInt value), interprets x as a numeric value, and creates the corresponding parts according to the effective locale and the formatting options of numberFormat. The following steps are taken:

  1. Let exponent be 0.
  2. If x is NaN, then
    1. Let n be an implementation- and locale-dependent (ILD) String value indicating the NaN value.
  3. Else if x is not a finite Number or BigInt,
    1. Let n be an ILD String value indicating infinity.
  4. Else,
    1. If numberFormat.[[Style]] is "percent", let x be 100 × x.
    2. Let exponent be ComputeExponent(numberFormat, x).
    3. Let x be x × 10-exponent.
    4. Let formatNumberResult be FormatNumericToString(numberFormat, x).
    5. Let n be formatNumberResult.[[FormattedString]].
    6. Let x be formatNumberResult.[[RoundedNumber]].
  5. Let pattern be GetNumberFormatPattern(numberFormat, x)
  6. Let result be a new empty List.
  7. Let patternParts be PartitionPattern(pattern).
  8. For each element patternPart of patternParts, in List order, do
    1. Let p be patternPart.[[Type]].
    2. If p is "literal", then
      1. Add new part record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } as a new element of result.
    3. Else if p is equal to "number", then
      1. Let notationSubParts be PartitionNotationSubPattern(numberFormat, x, n, exponent).
      2. Append all elements of notationSubParts to result.
    4. Else if p is equal to "plusSign", then
      1. Let plusSignSymbol be the ILND String representing the plus sign.
      2. Append a new Record { [[Type]]: "plusSign", [[Value]]: plusSignSymbol } as the last element of result.
    5. Else if p is equal to "minusSign", then
      1. Let minusSignSymbol be the ILND String representing the minus sign.
      2. Append a new Record { [[Type]]: "minusSign", [[Value]]: minusSignSymbol } as the last element of result.
    6. Else if p is equal to "percentSign" and numberFormat.[[Style]] is "percent", then
      1. Let percentSignSymbol be the ILND String representing the percent sign.
      2. Append a new Record { [[Type]]: "percentSign", [[Value]]: percentSignSymbol } as the last element of result.
    7. Else if p is equal to "unitPrefix" and numberFormat.[[Style]] is "unit", then
      1. Let unit be numberFormat.[[Unit]].
      2. Let unitDisplay be numberFormat.[[UnitDisplay]].
      3. Let mu be an ILD String value representing unit before x in unitDisplay form, which may depend on x in languages having different plural forms.
      4. Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
    8. Else if p is equal to "unitSuffix" and numberFormat.[[Style]] is "unit", then
      1. Let unit be numberFormat.[[Unit]].
      2. Let unitDisplay be numberFormat.[[UnitDisplay]].
      3. Let mu be an ILD String value representing unit after x in unitDisplay form, which may depend on x in languages having different plural forms.
      4. Append a new Record { [[Type]]: "unit", [[Value]]: mu } as the last element of result.
    9. Else if p is equal to "currencyCode" and numberFormat.[[Style]] is "currency", then
      1. Let currency be numberFormat.[[Currency]].
      2. Let cd be currency.
      3. Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
    10. Else if p is equal to "currencyPrefix" and numberFormat.[[Style]] is "currency", then
      1. Let currency be numberFormat.[[Currency]].
      2. Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
      3. Let cd be an ILD String value representing currency before x in currencyDisplay form, which may depend on x in languages having different plural forms.
      4. Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
    11. Else if p is equal to "currencySuffix" and numberFormat.[[Style]] is "currency", then
      1. Let currency be numberFormat.[[Currency]].
      2. Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
      3. Let cd be an ILD String value representing currency after x in currencyDisplay form, which may depend on x in languages having different plural forms. If the implementation does not have such a representation of currency, use currency itself.
      4. Append a new Record { [[Type]]: "currency", [[Value]]: cd } as the last element of result.
    12. Else,
      1. Let unknown be an ILND String based on x and p.
      2. Append a new Record { [[Type]]: "unknown", [[Value]]: unknown } as the last element of result.
  9. Return result.

1.1.7PartitionNotationSubPattern ( numberFormat, x, n, exponent )

The PartitionNotationSubPattern abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat), x (which is a numeric value after rounding is applied), n (which is an intermediate formatted string), and exponent (an integer), and creates the corresponding parts for the number and notation according to the effective locale and the formatting options of numberFormat. The following steps are taken:

  1. Let result be a new empty List.
  2. If x is NaN, then
    1. Append a new Record { [[Type]]: "nan", [[Value]]: n } as the last element of result.
  3. Else if x is not a finite Number or BigInt,
    1. Append a new Record { [[Type]]: "infinity", [[Value]]: n } as the last element of result.
  4. Else,
    1. Let notationSubPattern be GetNotationSubPattern(numberFormat, exponent)
    2. Let patternParts be PartitionPattern(notationSubPattern).
    3. For each element patternPart of patternParts, in List order, do
      1. Let p be patternPart.[[Type]].
      2. If p is "literal", then
        1. Add new part record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } as a new element of result.
      3. Else If p is equal to "number", then
        1. If the numberFormat.[[NumberingSystem]] matches one of the values in the "Numbering System" column of Table 1 below, then
          1. Let digits be a List whose 10 String valued elements are the UTF-16 string representations of the 10 digits specified in the "Digits" column of the matching row in Table 1.
          2. Replace each digit in n with the value of digits[digit].
        2. Else use an implementation dependent algorithm to map n to the appropriate representation of n in the given numbering system.
        3. Let decimalSepIndex be Call(%StringProto_indexOf%, n, « ".", 0 »).
        4. If decimalSepIndex > 0, then
          1. Let integer be the substring of n from position 0, inclusive, to position decimalSepIndex, exclusive.
          2. Let fraction be the substring of n from position decimalSepIndex, exclusive, to the end of n.
        5. Else,
          1. Let integer be n.
          2. Let fraction be undefined.
        6. If the numberFormat.[[UseGrouping]] is true, then
          1. Let groupSepSymbol be the implementation-, locale-, and numbering system-dependent (ILND) String representing the grouping separator.
          2. Let groups be a List whose elements are, in left to right order, the substrings defined by ILND set of locations within the integer.
          3. Assert: The number of elements in groups List is greater than 0.
          4. Repeat, while groups List is not empty
            1. Remove the first element from groups and let integerGroup be the value of that element.
            2. Append a new Record { [[Type]]: "integer", [[Value]]: integerGroup } as the last element of result.
            3. If groups List is not empty, then
              1. Append a new Record { [[Type]]: "group", [[Value]]: groupSepSymbol } as the last element of result.
        7. Else,
          1. Append a new Record { [[Type]]: "integer", [[Value]]: integer } as the last element of result.
        8. If fraction is not undefined, then
          1. Let decimalSepSymbol be the ILND String representing the decimal separator.
          2. Append a new Record { [[Type]]: "decimal", [[Value]]: decimalSepSymbol } as the last element of result.
          3. Append a new Record { [[Type]]: "fraction", [[Value]]: fraction } as the last element of result.
      4. Else if p is equal to "compactSymbol", then
        1. Let compactSymbol be an ILD string representing exponent in short form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactSymbol}" placeholder.
        2. Append a new Record { [[Type]]: "compact", [[Value]]: compactSymbol } as the last element of result.
      5. Else if p is equal to "compactName", then
        1. Let compactName be an ILD string representing exponent in long form, which may depend on x in languages having different plural forms. The implementation must be able to provide this string, or else the pattern would not have a "{compactName}" placeholder.
        2. Append a new Record { [[Type]]: "compact", [[Value]]: compactName } as the last element of result.
      6. Else if p is equal to "scientificSeparator", then
        1. Let scientificSeparator be the ILND String representing the exponent separator.
        2. Append a new Record { [[Type]]: "exponentSeparator", [[Value]]: scientificSeparator } as the last element of result.
      7. Else if p is equal to "scientificExponent", then
        1. If exponent < 0, then
          1. Let minusSignSymbol be the ILND String representing the minus sign.
          2. Append a new Record { [[Type]]: "exponentMinusSign", [[Value]]: minusSignSymbol } as the last element of result.
          3. Let exponent be -exponent.
        2. Let exponentResult be ToRawFixed(exponent, 1, 0, 0).
        3. Append a new Record { [[Type]]: "exponentInteger", [[Value]]: exponentResult.[[FormattedString]] } as the last element of result.
      8. Else,
        1. Let unknown be an ILND String based on x and p.
        2. Append a new Record { [[Type]]: "unknown", [[Value]]: unknown } as the last element of result.
  5. Return result.
Table 1: Numbering systems with simple digit mappings
Numbering System Digits
arab U+0660 to U+0669
arabext U+06F0 to U+06F9
bali U+1B50 to U+1B59
beng U+09E6 to U+09EF
deva U+0966 to U+096F
fullwide U+FF10 to U+FF19
gujr U+0AE6 to U+0AEF
guru U+0A66 to U+0A6F
hanidec U+3007, U+4E00, U+4E8C, U+4E09, U+56DB, U+4E94, U+516D, U+4E03, U+516B, U+4E5D
khmr U+17E0 to U+17E9
knda U+0CE6 to U+0CEF
laoo U+0ED0 to U+0ED9
latn U+0030 to U+0039
limb U+1946 to U+194F
mlym U+0D66 to U+0D6F
mong U+1810 to U+1819
mymr U+1040 to U+1049
orya U+0B66 to U+0B6F
tamldec U+0BE6 to U+0BEF
telu U+0C66 to U+0C6F
thai U+0E50 to U+0E59
tibt U+0F20 to U+0F29
Note 1
The computations rely on String values and locations within numeric strings that are dependent upon the implementation and the effective locale of numberFormat ("ILD") or upon the implementation, the effective locale, and the numbering system of numberFormat ("ILND"). The ILD and ILND Strings mentioned, other than those for currency names, must not contain any characters in the General Category "Number, decimal digit" as specified by the Unicode Standard.
Note 2
It is recommended that implementations use the locale provided by the Common Locale Data Repository (available at http://cldr.unicode.org).

1.1.8FormatNumeric( numberFormat, x )

The FormatNumeric abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat) and x (which must be a Number or BigInt value), and performs the following steps:

  1. Let parts be ? PartitionNumberPattern(numberFormat, x).
  2. Let result be the empty String.
  3. For each part in parts, do
    1. Set result to the string-concatenation of result and part.[[Value]].
  4. Return result.

1.1.9FormatNumericToParts( numberFormat, x )

The FormatNumericToParts abstract operation is called with arguments numberFormat (which must be an object initialized as a NumberFormat) and x (which must be a Number or BigInt value), and performs the following steps:

  1. Let parts be ? PartitionNumberPattern(numberFormat, x).
  2. Let result be ArrayCreate(0).
  3. Let n be 0.
  4. For each part in parts, do
    1. Let O be ObjectCreate(%ObjectPrototype%).
    2. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
    3. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
    4. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), O).
    5. Increment n by 1.
  5. Return result.

1.1.10ToRawPrecision( x, minPrecision, maxPrecision )

When the ToRawPrecision abstract operation is called with arguments x (which must be a finite non-negative Number or BigInt), minPrecision, and maxPrecision (both must be integers between 1 and 21), the following steps are taken:

  1. Let p be maxPrecision.
  2. If x = 0, then
    1. Let m be the String consisting of p occurrences of the character "0".
    2. Let e be 0.
    3. Let xFinal be 0.
  3. Else,
    1. Let e be the base 10 logarithm of x rounded down to the nearest integer.
    2. Let n be an integer such that 10p–1n < 10p and for which the exact mathematical value of n × 10ep+1x is as close to zero as possible. If there is more than one such n, pick the one for which n × 10ep+1 is larger.
    3. Let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
    4. Let xFinal be n × 10ep+1.
  4. If ep–1, then
    1. Let m be the string-concatenation of m and ep+1 occurrences of the character "0".
    2. Let int be e+1.
  5. Else if e ≥ 0, then
    1. Let m be the string-concatenation of the first e+1 characters of m, the character ".", and the remaining p–(e+1) characters of m.
    2. Let int be e+1.
  6. Else,
    1. Assert: e < 0.
    2. Let m be the string-concatenation of the String value "0.", –(e+1) occurrences of the character "0", and m.
    3. Let int be 1.
  7. If m contains the character ".", and maxPrecision > minPrecision, then
    1. Let cut be maxPrecisionminPrecision.
    2. Repeat, while cut > 0 and the last character of m is "0"
      1. Remove the last character from m.
      2. Decrease cut by 1.
    3. If the last character of m is ".", then
      1. Remove the last character from m.
  8. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int }.

1.1.11ToRawFixed( x, minInteger, minFraction, maxFraction )

When the ToRawFixed abstract operation is called with arguments x (which must be a finite non-negative Number or BigInt), minInteger (which must be an integer between 1 and 21), minFraction, and maxFraction (which must be integers between 0 and 20), the following steps are taken:

  1. Let f be maxFraction.
  2. Let n be an integer for which the exact mathematical value of n ÷ 10fx is as close to zero as possible. If there are two such n, pick the larger n.
  3. Let xFinal be n ÷ 10f.
  4. If n = 0, let m be the String "0". Otherwise, let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
  5. If f ≠ 0, then
    1. Let k be the number of characters in m.
    2. If kf, then
      1. Let z be the String value consisting of f+1–k occurrences of the character "0".
      2. Let m be the string-concatenation of z and m.
      3. Let k be f+1.
    3. Let a be the first kf characters of m, and let b be the remaining f characters of m.
    4. Let m be the string-concatenation of a, ".", and b.
    5. Let int be the number of characters in a.
  6. Else, let int be the number of characters in m.
  7. Let cut be maxFractionminFraction.
  8. Repeat, while cut > 0 and the last character of m is "0"
    1. Remove the last character from m.
    2. Decrease cut by 1.
  9. If the last character of m is ".", then
    1. Remove the last character from m.
  10. Return the Record { [[FormattedString]]: m, [[RoundedNumber]]: xFinal, [[IntegerDigitsCount]]: int }.

1.1.12UnwrapNumberFormat( nf )

The UnwrapNumberFormat abstract operation gets the underlying NumberFormat operation for various methods which implement ECMA-402 v1 semantics for supporting initializing existing Intl objects.

  1. Assert: Type(nf) is Object.
  1. If nf does not have an [[InitializedNumberFormat]] internal slot and ? InstanceofOperator(nf, %NumberFormat%) is true, then
    1. Let nf be ? Get(nf, %Intl%.[[FallbackSymbol]]).
  1. If Type(nf) is not Object or nf does not have an [[InitializedNumberFormat]] internal slot, then
    1. Throw a TypeError exception.
  2. Return nf.
Note
See for the motivation of the normative optional text.

1.1.13SetNumberFormatUnitOptions ( intlObj, options )

The abstract operation SetNumberFormatUnitOptions resolves the user-specified options relating to units onto the intl object.

  1. Assert: Type(intlObj) is Object.
  2. Assert: Type(options) is Object.
  3. Let style be ? GetOption(options, "style", "string", « "decimal", "percent", "currency", "unit" », "decimal").
  4. Set intlObj.[[Style]] to style.
  5. Let currency be ? GetOption(options, "currency", "string", undefined, undefined).
  6. If currency is not undefined, then
    1. If the result of IsWellFormedCurrencyCode(currency) is false, throw a RangeError exception.
  7. Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
  8. Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard").
  9. Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
  10. If unit is not undefined, then
    1. If the result of IsWellFormedUnitIdentifier(unit) is false, throw a RangeError exception.
  11. Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
  12. If style is "currency", then
    1. If currency is undefined, throw a TypeError exception.
    2. Let currency be the result of converting currency to upper case as specified in .
    3. Set intlObj.[[Currency]] to currency.
    4. Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
    5. Set intlObj.[[CurrencySign]] to currencySign.
  13. If style is "unit", then
    1. If unit is undefined, throw a TypeError exception.
    2. Set intlObj.[[Unit]] to unit.
    3. Set intlObj.[[UnitDisplay]] to unitDisplay.

1.1.14GetNumberFormatPattern ( numberFormat, x )

The abstract operation GetNumberFormatPattern considers the resolved unit-related options in the number format object along with the final scaled and rounded number being formatted and returns a pattern, a String value as described in 1.3.3.

  1. Let localeData be %NumberFormat%.[[LocaleData]].
  2. Let dataLocale be numberFormat.[[DataLocale]].
  3. Let dataLocaleData be localeData.[[<dataLocale>]].
  4. Let patterns be dataLocaleData.[[patterns]].
  5. Assert: patterns is a Record (see 1.3.3).
  6. Let style be numberFormat.[[Style]].
  7. If style is "percent", then
    1. Let patterns be patterns.[[percent]].
  8. Else if style is "unit", then
    1. Let unit be numberFormat.[[Unit]].
    2. Let unitDisplay be numberFormat.[[UnitDisplay]].
    3. Let patterns be patterns.[[unit]].
    4. If patterns.[[<unit>]] is undefined, then
      1. Let unit be "fallback".
    5. Let patterns be patterns.[[<unit>]].
    6. Let patterns be patterns.[[<unitDisplay>]].
  9. Else if style is "currency", then
    1. Let currency be numberFormat.[[Currency]].
    2. Let currencyDisplay be numberFormat.[[CurrencyDisplay]].
    3. Let currencySign be numberFormat.[[CurrencySign]].
    4. Let patterns be patterns.[[currency]].
    5. If patterns.[[<currency>]] is undefined, then
      1. Let currency be "fallback".
    6. Let patterns be patterns.[[<currency>]].
    7. Let patterns be patterns.[[<currencyDisplay>]].
    8. Let patterns be patterns.[[<currencySign>]].
  10. Else,
    1. Assert: style is "decimal".
    2. Let patterns be patterns.[[decimal]].
  11. Let signDisplay be numberFormat.[[SignDisplay]].
  12. If signDisplay is "never", then
    1. Let pattern be patterns.[[zeroPattern]].
  13. Else if signDisplay is "auto", then
    1. If x is 0 or x > 0 or x is NaN, then
      1. Let pattern be patterns.[[zeroPattern]].
    2. Else,
      1. Let pattern be patterns.[[negativePattern]].
  14. Else if signDisplay is "always", then
    1. If x is 0 or x > 0 or x is NaN, then
      1. Let pattern be patterns.[[positivePattern]].
    2. Else,
      1. Let pattern be patterns.[[negativePattern]].
  15. Else,
    1. Assert: signDisplay is "exceptZero".
    2. If x is 0 or x is -0 or x is NaN, then
      1. Let pattern be patterns.[[zeroPattern]].
    3. Else if x > 0, then
      1. Let pattern be patterns.[[positivePattern]].
    4. Else,
      1. Let pattern be patterns.[[negativePattern]].
  16. Return pattern.

1.1.15GetNotationSubPattern ( numberFormat, exponent )

The abstract operation GetNotationSubPattern considers the resolved notation and exponent, and returns a String value for the notation sub pattern as described in 1.3.3.

  1. Let localeData be %NumberFormat%.[[LocaleData]].
  2. Let dataLocale be numberFormat.[[DataLocale]].
  3. Let dataLocaleData be localeData.[[<dataLocale>]].
  4. Let notationSubPatterns be dataLocaleData.[[notationSubPatterns]].
  5. Assert: notationSubPatterns is a Record (see 1.3.3).
  6. Let notation be numberFormat.[[Notation]].
  7. If notation is "scientific" or notation is "engineering", then
    1. Return notationSubPatterns.[[scientific]].
  8. Else if exponent is not 0, then
    1. Assert: notation is "compact".
    2. Let compactDisplay be numberFormat.[[CompactDisplay]].
    3. Let compactPatterns be notationSubPatterns.[[compact]].[[>compactDisplay<]].
    4. Return compactPatterns.[[exponent]].
  9. Else,
    1. Return "{number}".

1.1.16ComputeExponent ( numberFormat, x )

The abstract operation ComputeExponent computes an exponent (power of ten) by which to scale x according to the number formatting settings. It handles cases such as 999 rounding up to 1000, requiring a different exponent.

  1. If x = 0, then
    1. Return 0.
  2. If x < 0, then
    1. Let x = -x.
  3. Let magnitude be the base 10 logarithm of x rounded down to the nearest integer.
  4. Let exponent be ComputeExponentForMagnitude(numberFormat, magnitude).
  5. Let x be x × 10-exponent.
  6. Let formatNumberResult be FormatNumericToString(numberFormat, x).
  7. If formatNumberResult.[[RoundedNumber]] = 0, then
    1. Return exponent.
  8. Let newMagnitude be the base 10 logarithm of x rounded down to the nearest integer.
  9. If newMagnitude is magnitudeexponent, then
    1. Return exponent.
  10. Return ComputeExponentForMagnitude(numberFormat, magnitude + 1).

1.1.17ComputeExponentForMagnitude ( numberFormat, magnitude )

The abstract operation ComputeExponentHelper computes an exponent by which to scale a number of the given magnitude (power of ten of the most significant digit) according to the locale and the desired notation (scientific, engineering, or compact).

  1. Let notation be numberFormat.[[Notation]].
  2. If notation is "standard", then
    1. Return 0.
  3. Else if notation is "scientific", then
    1. Return magnitude.
  4. Else if notation is "engineering", then
    1. Let thousands be the greatest integer that is not greater than magnitude ÷ 3.
    2. Return thousands × 3.
  5. Else,
    1. Assert: notation is "compact".
    2. Let exponent be an implementation- and locale-dependent (ILD) integer by which to scale a number of the given magnitude in compact notation for the current locale.
    3. Return exponent.

1.2The Intl.NumberFormat Constructor

The NumberFormat constructor is the %NumberFormat% 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 .

1.2.1Intl.NumberFormat ( [ locales [ , options ] ] )

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

  1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
  2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormatPrototype%", « [[InitializedNumberFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[Unit]], [[UnitDisplay]], [[Currency]], [[CurrencyDisplay]], [[CurrencySign]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]], [[Notation]], [[CompactDisplay]], [[UseGrouping]], [[SignDisplay]], [[BoundFormat]] »).
  3. Perform ? InitializeNumberFormat(numberFormat, locales, options).
  1. Let this be the this value.
  2. If NewTarget is undefined and ? InstanceofOperator(this, %NumberFormat%) is true, then
    1. Perform ? DefinePropertyOrThrow(this, %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]: numberFormat, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
    2. Return this.
  1. Return numberFormat.
Note
See for the motivation of the normative optional text.

1.3Properties of the Intl.NumberFormat Constructor

The Intl.NumberFormat constructor has the following properties:

1.3.1Intl.NumberFormat.prototype

The value of Intl.NumberFormat.prototype is %NumberFormatPrototype%.

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

1.3.2Intl.NumberFormat.supportedLocalesOf ( locales [ , options ] )

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

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

The value of the length property of the supportedLocalesOf method is 1.

1.3.3Internal slots

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

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

Note 1
Unicode Technical Standard 35 describes two locale extension keys that are relevant to number formatting, "nu" for numbering system and "cu" for currency. Intl.NumberFormat, however, requires that the currency of a currency format is specified through the currency property in the options objects.

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

  • The list that is the value of the "nu" field of any locale field of [[LocaleData]] must not include the values "native", "traditio", or "finance".
  • [[LocaleData]].[[<locale>]] must have a [[patterns]] field for all locale values locale. The value of this field must be a Record, which must have fields with the names of the four number format styles: "decimal", "percent", "currency", and "unit".
  • The two fields "currency" and "unit" noted above must be Records with at least one field, "fallback". The "currency" may have additional fields with keys corresponding to currency codes according to . Each field of "currency" must be a Record with fields corresponding to the possible currencyDisplay values: "code", "symbol", "narrowSymbol", and "name". Each of those fields must contain a Record with fields corresponding to the possible currencySign values: "standard" or "accounting". The "unit" field (of [[LocaleData]].[[<locale>]]) may have additional fields beyond the required field "fallback" with keys corresponding to core measurement unit identifiers corresponding to . Each field of "unit" must be a Record with fields corresponding to the possible unitDisplay values: "narrow", "short", and "long".
  • All of the leaf fields so far described for the patterns tree ("decimal", "percent", great-grandchildren of "currency", and grandchildren of "unit") must be Records with the keys "positivePattern", "zeroPattern", and "negativePattern".
  • The value of the aforementioned fields (the sign-dependent pattern fields) must be string values that must contain the substring "{number}". "positivePattern" must contain the substring "{plusSign}" but not "{minusSign}"; "negativePattern" must contain the substring "{minusSign}" but not "{plusSign}"; and "zeroPattern" must not contain either "{plusSign}" or "{minusSign}". Additionally, the values within the "percent" field must also contain the substring "{percentSign}"; the values within the "currency" field must also contain one or more of the following substrings: "{currencyCode}", "{currencyPrefix}", or "{currencySuffix}"; and the values within the "unit" field must also contain one or more of the following substrings: "{unitPrefix}" or "{unitSuffix}". The pattern strings must not contain any characters in the General Category "Number, decimal digit" as specified by the Unicode Standard.
  • [[LocaleData]].[[<locale>]] must also have a [[notationSubPatterns]] field for all locale values locale. The value of this field must be a Record, which must have two fields: [[scientific]] and [[compact]]. The [[scientific]] field must be a string value containing the substrings "{number}", "{scientificSeparator}", and "{scientificExponent}". The [[compact]] field must be a Record with two fields: "short" and "long". Each of these fields must be a Record with integer keys corresponding to all discrete magnitudes the implementation supports for compact notation. Each of these fields must be a string value which may contain the substring "{number}". Strings descended from "short" must contain the substring "{compactSymbol}", and strings descended from "long" must contain the substring "{compactName}".
Note 2
It is recommended that implementations use the locale data provided by the Common Locale Data Repository (available at http://cldr.unicode.org).

1.4Properties of the Intl.NumberFormat Prototype Object

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

1.4.1Intl.NumberFormat.prototype.constructor

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

1.4.2Intl.NumberFormat.prototype [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Object".

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

1.4.3get Intl.NumberFormat.prototype.format

Intl.NumberFormat.prototype.format is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let nf be the this value.
  2. If Type(nf) is not Object, throw a TypeError exception.
  3. Let nf be ? UnwrapNumberFormat(nf).
  4. If nf.[[BoundFormat]] is undefined, then
    1. Let F be a new built-in function object as defined in Number Format Functions (1.1.4).
    2. Set F.[[NumberFormat]] to nf.
    3. Set nf.[[BoundFormat]] to F.
  5. Return nf.[[BoundFormat]].
Note
The returned function is bound to nf so that it can be passed directly to Array.prototype.map or other functions. This is considered a historical artefact, as part of a convention which is no longer followed for new features, but is preserved to maintain compatibility with existing programs.

1.4.4Intl.NumberFormat.prototype.formatToParts ( value )

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

  1. Let nf be the this value.
  2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]).
  3. Let x be ? ToNumeric(value).
  4. Return ? FormatNumericToParts(nf, x).

1.4.5Intl.NumberFormat.prototype.resolvedOptions ()

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

  1. Let nf be this value.
  2. If Type(nf) is not Object, throw a TypeError exception.
  3. Let nf be ? UnwrapNumberFormat(nf).
  4. Let options be ! ObjectCreate(%ObjectPrototype%).
  5. For each row of Table 2, 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 nf's internal slot whose name is the Internal Slot value of the current row.
    3. If v is not undefined, then
      1. Perform ! CreateDataPropertyOrThrow(options, p, v).
  6. Return options.
Table 2: Resolved Options of NumberFormat Instances
Internal Slot Property
[[Locale]] "locale"
[[NumberingSystem]] "numberingSystem"
[[Style]] "style"
[[Currency]] "currency"
[[CurrencyDisplay]] "currencyDisplay"
[[CurrencySign]] "currencySign"
[[Unit]] "unit"
[[UnitDisplay]] "unitDisplay"
[[MinimumIntegerDigits]] "minimumIntegerDigits"
[[MinimumFractionDigits]] "minimumFractionDigits"
[[MaximumFractionDigits]] "maximumFractionDigits"
[[MinimumSignificantDigits]] "minimumSignificantDigits"
[[MaximumSignificantDigits]] "maximumSignificantDigits"
[[UseGrouping]] "useGrouping"
[[Notation]] "notation"
[[CompactDisplay]] "compactDisplay"
[[SignDisplay]] "signDisplay"

1.5Properties of Intl.NumberFormat Instances

Intl.NumberFormat instances are ordinary objects that inherit properties from %NumberFormatPrototype%.

Intl.NumberFormat instances have an [[InitializedNumberFormat]] internal slot.

Intl.NumberFormat 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 "decimal", "currency", "percent", or "unit", identifying the type of quantity being measured.
  • [[Currency]] is a String value with the currency code identifying the currency to be used if formatting with the "currency" unit type. It is only used when [[Style]] has the value "currency".
  • [[CurrencyDisplay]] is one of the String values "code", "symbol", "narrowSymbol", or "name", specifying whether to display the currency as an ISO 4217 alphabetic currency code, a localized currency symbol, or a localized currency name if formatting with the "currency" style. It is only used when [[Style]] has the value "currency".
  • [[CurrencySign]] is one of the String values "standard" or "accounting", specifying whether to render negative numbers in accounting format, often signified by parenthesis. It is only used when [[Style]] has the value "currency" and when [[SignDisplay]] is not "never".
  • [[Unit]] is a core unit identifier, as defined by Unicode Technical Standard #35, Part 2, Section 6. It is only used when [[Style]] has the value "unit".
  • [[UnitDisplay]] is one of the String values "short", "narrow", or "long", specifying whether to display the unit as a symbol, narrow symbol, or localized long name if formatting with the "unit" style. It is only used when [[Style]] has the value "unit".
  • [[MinimumIntegerDigits]] is a non-negative integer Number value indicating the minimum integer digits to be used. Numbers will be padded with leading zeroes if necessary.
  • [[MinimumFractionDigits]] and [[MaximumFractionDigits]] are non-negative integer Number values indicating the minimum and maximum fraction digits to be used. Numbers will be rounded or padded with trailing zeroes if necessary. These properties are only used when [[RoundingType]] is fractionDigits.
  • [[MinimumSignificantDigits]] and [[MaximumSignificantDigits]] are positive integer Number values indicating the minimum and maximum fraction digits to be shown. If present, the formatter uses however many fraction digits are required to display the specified number of significant digits. These properties are only used when [[RoundingType]] is significantDigits.
  • [[UseGrouping]] is a Boolean value indicating whether a grouping separator should be used.
  • [[RoundingType]] is one of the String values fractionDigits, significantDigits, or compactRounding, indicating which rounding strategy to use. If fractionDigits, the number is rounded according to [[MinimumFractionDigits]] and [[MaximumFractionDigits]], as described above. If significantDigits, the number is rounded according to [[MinimumSignificantDigits]] and [[MaximumSignificantDigits]] as described above. If compactRounding, the number is rounded to 1 maximum fraction digit if there is 1 digit before the decimal separator, and otherwise round to 0 fraction digits.
  • [[Notation]] is one of the String values "standard", "scientific", "engineering", or "compact", specifying whether the number should be displayed without scaling, scaled to the units place with the power of ten in scientific notation, scaled to the nearest thousand with the power of ten in scientific notation, or scaled to the nearest locale-dependent compact decimal notation power of ten with the corresponding compact decimal notation affix.
  • [[CompactDisplay]] is one of the String values "short" or "long", specifying whether to display compact notation affixes in short form ("5K") or long form ("5 thousand") if formatting with the "compact" notation. It is only used when [[Notation]] has the value "compact".
  • [[SignDisplay]] is one of the String values "auto", "always", "never", or "exceptZero", specifying whether to show the sign on negative numbers only, positive and negative numbers including zero, neither positive nor negative numbers, or positive and negative numbers but not zero. In scientific notation, this slot affects the sign display of the mantissa but not the exponent.

Finally, Intl.NumberFormat instances have a [[BoundFormat]] internal slot that caches the function returned by the format accessor (1.4.3).