Intl.RelativeTimeFormat Spec Proposal

1RelativeTimeFormat Objects

1.1Abstract Operations for RelativeTimeFormat Objects

1.1.1InitializeRelativeTimeFormat ( relativeTimeFormat, locales, options )

The abstract operation InitializeRelativeTimeFormat accepts the arguments relativeTimeFormat (which must be an object), locales, and options. It initializes relativeTimeFormat as a RelativeTimeFormat 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 numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
  8. If numberingSystem is not undefined, then
    1. If numberingSystem does not match the (3*8alphanum) *("-" (3*8alphanum)) sequence, throw a RangeError exception.
  9. Set opt.[[nu]] to numberingSystem.
  10. Let localeData be %RelativeTimeFormat%.[[LocaleData]].
  11. Let r be ResolveLocale(%RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %RelativeTimeFormat%.[[RelevantExtensionKeys]], localeData).
  12. Let locale be r.[[Locale]].
  13. Set relativeTimeFormat.[[Locale]] to locale.
  14. Set relativeTimeFormat.[[NumberingSystem]] to r.[[nu]].
  15. Let dataLocale be r.[[DataLocale]].
  16. Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long").
  17. Set relativeTimeFormat.[[Style]] to s.
  18. Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always").
  19. Set relativeTimeFormat.[[Numeric]] to numeric.
  20. Let fields be ! Get(localeData, dataLocale).
  21. Assert: fields is an object (see 1.3.3).
  22. Set relativeTimeFormat.[[Fields]] to fields.
  23. Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%NumberFormat%, « locale »).
  24. Let relativeTimeFormat.[[PluralRules]] be ! Construct(%PluralRules%, « locale »).
  25. Return relativeTimeFormat.

1.1.2SingularRelativeTimeUnit ( unit )

  1. Assert: Type(unit) is String.
  2. If unit is "seconds", return "second".
  3. If unit is "minutes", return "minute".
  4. If unit is "hours", return "hour".
  5. If unit is "days", return "day".
  6. If unit is "weeks", return "week".
  7. If unit is "months", return "month".
  8. If unit is "quarters", return "quarter".
  9. If unit is "years", return "year".
  10. If unit is not one of "second", "minute", "hour", "day", "week", "month", "quarter", or "year", throw a RangeError exception.
  11. Return unit.

1.1.3PartitionRelativeTimePattern ( relativeTimeFormat, value, unit )

When the FormatRelativeTime abstract operation is called with arguments relativeTimeFormat, value, and unit it returns a String value representing value (interpreted as a time value as specified in ES2016, 20.3.1.1) according to the effective locale and the formatting options of relativeTimeFormat.

  1. Assert: relativeTimeFormat has an [[InitializedRelativeTimeFormat]] internal slot.
  2. Assert: Type(value) is Number.
  3. Assert: Type(unit) is String.
  4. If value is NaN, +∞, or -∞, throw a RangeError exception.
  5. Let unit be ? SingularRelativeTimeUnit(unit).
  6. Let fields be relativeTimeFormat.[[Fields]].
  7. Let style be relativeTimeFormat.[[Style]].
  8. If style is equal to "short", then
    1. Let entry be the string-concatenation of unit and "-short".
  9. Else if style is equal to "narrow", then
    1. Let entry be the string-concatenation of unit and "-narrow".
  10. Else,
    1. Let entry be unit.
  11. Let exists be ! HasProperty(fields, entry).
  12. If exists is false, then
    1. Let entry be unit.
  13. Let patterns be ! Get(fields, entry).
  14. Let numeric be relativeTimeFormat.[[Numeric]].
  15. If numeric is equal to "auto", then
    1. Let exists be ! HasProperty(patterns, ! ToString(value)).
    2. If exists is true, then
      1. Let result be ! Get(patterns, ! ToString(value)).
      2. Return a List containing the Record { [[Type]]: "literal", [[Value]]: result }.
  16. If value is -0 or if value is less than 0, then
    1. Let tl be "past".
  17. Else,
    1. Let tl be "future".
  18. Let po be ! Get(patterns, tl).
  19. Let fv be ! PartitionNumberPattern(relativeTimeFormat.[[NumberFormat]], value).
  20. Let pr be ! ResolvePlural(relativeTimeFormat.[[PluralRules]], value).
  21. Let pattern be ! Get(po, pr).
  22. Return ! MakePartsList(pattern, unit, fv).

1.1.4MakePartsList ( pattern, unit, parts )

The MakePartsList abstract operation is called with arguments pattern, a pattern String, unit, a String, and parts, a List of Records representing a formatted Number. Note

Example:

          MakePartsList("AA{0}BB", "hour", « { [[Type]]: "integer", [[Value]]: "15" } » )

        Output (List of Records):
          «
            { [[Type]]: "literal", [[Value]]: "AA"},
            { [[Type]]: "integer", [[Value]]: "15", [[Unit]]: "hour"},
            { [[Type]]: "literal", [[Value]]: "BB"}
          »
        

  1. Let result be a new empty List.
  2. Let beginIndex be ! Call(%StringProto_indexOf%, pattern, « "{", 0 »).
  3. Let length be the number of elements in pattern.
  4. Repeat, while beginIndex is an integer index into pattern
    1. Set endIndex to ! Call(%StringProto_indexOf%, pattern, « "}", beginIndex »).
    2. Assert: endIndex is not -1, otherwise the pattern would be malformed.
    3. If beginIndex is greater than nextIndex, then
      1. Let literal be a substring of pattern from position nextIndex, inclusive, to position beginIndex, exclusive.
      2. Add new part Record { [[Type]]: "literal", [[Value]]: literal } as a new element of the list result.
    4. Let p be the substring of pattern from position beginIndex, exclusive, to position endIndex, exclusive.
    5. Assert: p is "0".
    6. For each part in parts, do
      1. Add new part Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: unit } as a new element on the List result.
  5. If nextIndex is less than length, then
    1. Let literal be the substring of pattern from position nextIndex, exclusive, to position length, exclusive.
    2. Add new part Record { [[Type]]: "literal", [[Value]]: literal } as a new element of the list result.
  6. Return result.

1.1.5FormatRelativeTime ( relativeTimeFormat, value, unit )

The FormatRelativeTime abstract operation is called with arguments relativeTimeFormat (which must be an object initialized as a RelativeTimeFormat), value (which must be a Number value), and unit (which must be a String denoting the value unit) and performs the following steps:

  1. Let parts be ? PartitionRelativeTimePattern(relativeTimeFormat, value, unit).
  2. Let result be an 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.6FormatRelativeTimeToParts ( relativeTimeFormat, value, unit )

The FormatRelativeTimeToParts abstract operation is called with arguments relativeTimeFormat (which must be an object initialized as a RelativeTimeFormat), value (which must be a Number value), and unit (which must be a String denoting the value unit) and performs the following steps:

  1. Let parts be ? PartitionRelativeTimePattern(relativeTimeFormat, value, unit).
  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. If part has a [[Unit]] field,
      1. Perform ! CreateDataPropertyOrThrow(O, "unit", part.[[Unit]]).
    5. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), O).
    6. Increment n by 1.
  5. Return result.

1.2The Intl.RelativeTimeFormat Constructor

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

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

When the Intl.RelativeTimeFormat function is called with optional arguments the following steps are taken:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let relativeTimeFormat be ? OrdinaryCreateFromConstructor(NewTarget, "%RelativeTimeFormatPrototype%", « [[InitializedRelativeTimeFormat]], [[Locale]], [[Style]], [[Numeric]], [[Fields]], [[NumberFormat]], [[NumberingSystem]], [[PluralRules]] »).
  3. Return ? InitializeRelativeTimeFormat(relativeTimeFormat, locales, options).

1.3Properties of the Intl.RelativeTimeFormat Constructor

The Intl.RelativeTimeFormat constructor has the following properties:

1.3.1Intl.RelativeTimeFormat.prototype

The value of Intl.RelativeTimeFormat.prototype is %RelativeTimeFormatPrototype%.

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

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

When the supportedLocalesOf method of %RelativeTimeFormat% is called, the following steps are taken:

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

1.3.3Internal slots

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" ».

Note 1
Unicode Technical Standard 35 implicitly describes one locale extension key that is relevant to relative time formatting, "nu" for numbering system.

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

  • [[LocaleData]][Locale] has ordinary data properties "second", "minute", "hour", "day", "week", "month", "quarter", and "year". Additional property keys may exist with the previous names concatenated with the strings "-narrow" or "-short". The values corresponding to these property keys are objects which contain these two categories of properties:
    • "future" and "past" properties, which are objects with a property for each of the [[PluralCategories]] in the Locale. The value corresponding to those properties is a pattern which may contain "{0}" to be replaced by a formatted number.
    • Optionally, additional properties whose key is the result of ToString of a Number, and whose values are literal Strings which are not treated as templates.
  • 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".
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.RelativeTimeFormat Prototype Object

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

1.4.1Intl.RelativeTimeFormat.prototype.constructor

The initial value of Intl.RelativeTimeFormat.prototype.constructor is %RelativeTimeFormat%.

1.4.2Intl.RelativeTimeFormat.prototype[ @@toStringTag ]

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

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

1.4.3Intl.RelativeTimeFormat.prototype.format( value, unit )

When the format method is called with arguments value and unit, the following steps are taken:

  1. Let relativeTimeFormat be the this value.
  2. If Type(relativeTimeFormat) is not Object, throw a TypeError exception.
  3. If relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot, throw a TypeError exception.
  4. Let value be ? ToNumber(value).
  5. Let unit be ? ToString(unit).
  6. Return ? FormatRelativeTime(relativeTimeFormat, value, unit).

1.4.4Intl.RelativeTimeFormat.prototype.formatToParts( value, unit )

When the formatToParts method is called with arguments value and unit, the following steps are taken:

  1. Let relativeTimeFormat be the this value.
  2. If Type(relativeTimeFormat) is not Object, throw a TypeError exception.
  3. If relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot, throw a TypeError exception.
  4. Let value be ? ToNumber(value).
  5. Let unit be ? ToString(unit).
  6. Return ? FormatRelativeTimeToParts(relativeTimeFormat, value, unit).

1.4.5Intl.RelativeTimeFormat.prototype.resolvedOptions ()

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

  1. Let relativeTimeFormat be the this value.
  2. If Type(relativeTimeFormat) is not Object, throw a TypeError exception.
  3. If relativeTimeFormat does not have an [[InitializedRelativeTimeFormat]] internal slot, throw a TypeError exception.
  4. Let options be ! ObjectCreate(%ObjectPrototype%).
  5. For each row of Table 1, 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 relativeTimeFormat's internal slot whose name is the Internal Slot value of the current row.
    3. Assert: v is not undefined.
    4. Perform ! CreateDataPropertyOrThrow(options, p, v).
  6. Return options.
Table 1: Resolved Options of RelativeTimeFormat Instances
Internal Slot Property
[[Locale]] "locale"
[[Style]] "style"
[[Numeric]] "numeric"
[[NumberingSystem]] "numberingSystem"

1.5Properties of Intl.RelativeTimeFormat Instances

Intl.RelativeTimeFormat instances are ordinary objects that inherit properties from %RelativeTimeFormatPrototype%.

Intl.RelativeTimeFormat instances have an [[InitializedRelativeTimeFormat]] internal slot.

Intl.RelativeTimeFormat 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.
  • [[Style]] is one of the String values "long", "short", or "narrow", identifying the relative time format style used.
  • [[Numeric]] is one of the String values "always" or "auto", identifying whether numerical descriptions are always used, or used only when no more specific version is available (e.g., "1 day ago" vs "yesterday").
  • [[NumberingSystem]] is a String value with the "type" given in Unicode Technical Standard 35 for the numbering system used for formatting.