diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html
index 30302d4e..33d9ada4 100644
--- a/spec/datetimeformat.html
+++ b/spec/datetimeformat.html
@@ -119,6 +119,7 @@
InitializeDateTimeFormat (dateTimeFormat, locales, options)
1. Let _pattern_ be Get(_bestFormat_, *"pattern"*).
1. Set _dateTimeFormat_.[[pattern]] to _pattern_.
1. Set _dateTimeFormat_.[[boundFormat]] to *undefined*.
+ 1. Set _dateTimeFormat_.[[boundFormatToParts]] to *undefined*.
1. Set _dateTimeFormat_.[[initializedDateTimeFormat]] to *true*.
1. Return _dateTimeFormat_.
@@ -224,35 +225,75 @@ DateTime Format Functions
1. Return FormatDateTime(_dtf_, _x_).
+
+ The function returned by [[Get]] is bound to this DateTimeFormat object so that it can be passed directly to Array.prototype.map or other functions.
+
+
The *length* property of a DateTime format function is 1.
-
- FormatDateTime (dateTimeFormat, x)
+
+ DateTime FormatToParts Functions
- When the FormatDateTime abstract operation is called with arguments _dateTimeFormat_ (which must be an object initialized as a DateTimeFormat) and _x_ (which must be a Number value), it returns a String value representing _x_ (interpreted as a time value as specified in ES2015, 20.3.1.1) according to the effective locale and the formatting options of _dateTimeFormat_. This abstract operation functions as follows:
+ A DateTime formatToParts function is an anonymous function that optionally takes an argument _date_. It performs the following steps:
+ 1. Let _dtf_ be the *this* value.
+ 1. Assert: Type(_dtf_) is Object and _dtf_ has an [[initializedDateTimeFormat]] internal slot whose value is *true*.
+ 1. If _date_ is not provided or is *undefined*, then
+ 1. Let _x_ be *%Date_now%*().
+ 1. Else,
+ 1. Let _x_ be ? ToNumber(_date_).
+ 1. Return FormatToPartsDateTime(_dtf_, _x_).
+
+
+
+ The function returned by [[Get]] is bound to this DateTimeFormat object so that it can be passed directly to Array.prototype.map or other functions.
+
+
+
+ The value of the [[Set]] attribute is *undefined*.
+
+
+
+
+
+ CreateDateTimeParts(dateTimeFormat, x)
+
+
+ The CreateDateTimeParts abstract operation is called with arguments _dateTimeFormat_ (which must be an object initialized as a DateTimeFormat) and _x_ (which must be a Number value), and performs the following steps:
+
+
+
1. If _x_ is not a finite Number, throw a *RangeError* exception.
1. Let _locale_ be the value of _dateTimeFormat_.[[locale]].
1. Let _nf_ be ? Construct(%NumberFormat%, « [locale], {useGrouping: *false*} »).
1. Let _nf2_ be ? Construct(%NumberFormat%, « [locale], {minimumIntegerDigits: 2, useGrouping: *false*} »).
1. Let _tm_ be ToLocalTime(_x_, _dateTimeFormat_.[[calendar]], _dateTimeFormat_.[[timeZone]]).
- 1. Let _result_ be the value of the _dateTimeFormat_.[[pattern]].
- 1. For each row of Table 3, except the header row, do:
- 1. If _dateTimeFormat_ has an internal slot with the name given in the Property column of the row, then
- 1. Let _p_ be the name given in the Property column of the row.
+ 1. Let _pattern_ be the value of the _dateTimeFormat_.[[pattern]].
+ 1. Let _result_ be a new empty List.
+ 1. Let _index_ be 0.
+ 1. Let _beginIndex_ be Call(*%StringProto_indexOf%*, _pattern_, "{", *0*).
+ 1. Let _endIndex_ be 0.
+ 1. Repeat while _beginIndex_ is an integer index into _pattern_:
+ 1. Set _endIndex_ to Call(*%StringProto_indexOf%*, _pattern_, "}", _beginIndex_)
+ 1. If _endIndex_ is *false*, throw new Error exception.
+ 1. If _beginIndex_ is greater than _index_, then:
+ 1. Let _separator_ be a new Record.
+ 1. Let _separatorValue_ be a substring of _pattern_ from position _index_, inclusive, to position _beginIndex_, exclusive.
+ 1. Add new part record { [[type]]: "separator", [[value]]: _separatorValue_ } as a new element of the list _result_.
+ 1. Let _p_ be the substring of _pattern_ from position _beginIndex_, exclusive, to position _endIndex_, exclusive.
+ 1. If _p_ matches a Property column of the row in Table 3, then:
1. Let _f_ be the value of the [[<_p_>]] internal slot of _dateTimeFormat_.
1. Let _v_ be the value of _tm_.[[<_p_>]].
1. If _p_ is *"year"* and _v_ ≤ 0, let _v_ be 1 - _v_.
1. If _p_ is *"month"*, increase _v_ by 1.
1. If _p_ is *"hour"* and the value of _dateTimeFormat_.[[hour12]] is *true*, then
1. Let _v_ be _v_ modulo 12.
- 1. If _v_ is equal to the value of _tm_.[[<_p_>]], let _pm_ be *false*; else let _pm_ be *true*.
1. If _v_ is 0 and the value of _dateTimeFormat_.[[hourNo0]] is *true*, let _v_ be 12.
1. If _f_ is *"numeric"*, then
1. Let _fv_ be FormatNumber(_nf_, _v_).
@@ -260,19 +301,82 @@ FormatDateTime (dateTimeFormat, x)
1. Let _fv_ be FormatNumber(_nf2_, _v_).
1. If the *length* property of _fv_ is greater than 2, let _fv_ be the substring of _fv_ containing the last two characters.
1. Else if _f_ is *"narrow"*, *"short"*, or *"long"*, then let _fv_ be a String value representing _f_ in the desired form; the String value depends upon the implementation and the effective locale and calendar of _dateTimeFormat_. If _p_ is *"month"*, then the String value may also depend on whether _dateTimeFormat_ has a [[day]] internal slot. If _p_ is *"timeZoneName"*, then the String value may also depend on the value of the [[inDST]] field of _tm_, and if the implementation does not have a localized representation of _f_, then use _f_ itself.
- 1. Replace the substring of _result_ that consists of *"{"*, p, and *"}"*, with _fv_.
- 1. If _dateTimeFormat_.[[hour12]] is *true*, then
- 1. If _pm_ is *true*, then
- 1. Let _fv_ be an implementation and locale dependent String value representing "post meridiem";
+ 1. Add new part record { [[type]]: _p_, [[value]]: _fv_ } as a new element of the list _result_.
+ 1. Else if _p_ is equal "ampm", then:
+ 1. Let _v_ be the value of _tm_.[[hour]].
+ 1. If _v_ is greater than 11, then:
+ 1. Let _fv_ be an implementation and locale dependent String value representing "post meridiem";
+ 1. Else,
+ 1. Let _fv_ be an implementation and locale dependent String value representing "ante meridiem".
+ 1. Add new part record { [[type]]: "dayperiod", [[value]]: _fv_ } as a new element of the list _result_.
1. Else,
- 1. Let _fv_ be an implementation and locale dependent String value representing "ante meridiem".
- 1. Replace the substring of _result_ that consists of *"{ampm}"*, with _fv_.
+ 1. Unknown token
+ 1. Let _separatorValue_ be the substring of _pattern_ from position _beginIndex_, inclusive, to position _endIndex_, inclusive.
+ 1. Add new part record { [[type]]: "separtor", [[value]]: _separatorValue_ } as a new element of the list _result_.
+ 1. Set _index_ to _endIndex_ + 1.
+ 1. Set _beginIndex_ to Call(*%StringProto_indexOf%*, _pattern_, "}", _index_)
+ 1. If _endIndex_ is less than _S_, then:
+ 1. Let _separator_ to be a new Record.
+ 1. Let _separatorValue_ be the substring of _pattern_ from position _endIndex_, exclusive, to position _S_, exclusive.
+ 1. Add new part record { [[type]]: "separator", [[value]]: _separatorValue_ } as a new element of the list _result_.
1. Return _result_.
+
+ CreateDateTimeParts abstract operation interpretes _x_ as a time value as specified in ES2015, 20.3.1.1; and create the corresponding parts according to the effective locale and the formatting options of _dateTimeFormat_.
+
+
It is recommended that implementations use the locale and calendar dependent strings provided by the Common Locale Data Repository (available at http://cldr.unicode.org/), and use CLDR "abbreviated" strings for DateTimeFormat "short" strings, and CLDR "wide" strings for DateTimeFormat "long" strings.
+
+
+ It is recommended that implementations use the time zone information of the IANA Time Zone Database.
+
+
+
+
+
+
+ FormatDateTime(dateTimeFormat, x)
+
+
+ The FormatDateTime abstract operation is called with arguments _dateTimeFormat_ (which must be an object initialized as a DateTimeFormat) and _x_ (which must be a Number value), and performs the following steps:
+
+
+
+ 1. Let _parts_ be CreateDateTimeParts(_dateTimneFormat_, _x_).
+ 1. Let _result_ be an empty string.
+ 1. For each _part_ in _parts_, do:
+ 1. Set _result_ to a String value produced by concatenating _result_ and _part_.[[value]].
+ 1. Return _result_.
+
+
+
+
+
+
+ FormatToPartDateTime(dateTimeFormat, x)
+
+
+ The FormatToPartDateTime abstract operation is called with arguments _dateTimeFormat_ (which must be an object initialized as a DateTimeFormat) and _x_ (which must be a Number value), and performs the following steps:
+
+
+
+ 1. Let _parts_ be CreateDateTimeParts(_dateTimneFormat_, _x_).
+ 1. Let _result_ be ArrayCreate(0).
+ 1. Let _n_ be 0.
+ 1. For each _part_ in _parts_, do:
+ 1. Let _O_ be ObjectCreate(%ObjectPrototype%).
+ 1. Let _typeDesc_ be the PropertyDescriptor{[[Value]]: _part_.[[type]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.
+ 1. Perform ? DefinePropertyOrThrow(_O_, "type", _typeDesc_).
+ 1. Let _valueDesc_ be the PropertyDescriptor{[[Value]]: _part_.[[value]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.
+ 1. Perform ? DefinePropertyOrThrow(_O_, "value", _valueDesc_).
+ 1. Perform ? CreateDataProperty(_result_, ? ToString(_n_), _O_).
+ 1. Increment _n_ by 1.
+ 1. Return _result_.
+
+
@@ -452,6 +556,26 @@ get Intl.DateTimeFormat.prototype.format
+
+ get Intl.DateTimeFormat.prototype.formatToParts
+
+
+ Intl.DateTimeFormat.prototype.formatToParts is an accessor property whose set accessor function is *undefined*. Its get accessor function performs the following steps:
+
+
+
+ 1. Let _dtf_ be *this* value.
+ 1. If Type(_dtf_) is not Object, throw a *TypeError* exception.
+ 1. If _dtf_ does not have a [[boundFormatToParts]] internal slot, throw a *TypeError* exception.
+ 1. If the [[boundFormatToParts]] internal slot of _dtf_ is *undefined*, then
+ 1. Let _F_ be a new built-in function object as defined in DateTime Format Functions ().
+ 1. The value of _F_’s *length* property is 1.
+ 1. Let _bf_ be BoundFunctionCreate(_F_, _dft_).
+ 1. Set _dtf_.[[boundFormatToParts]] to _bf_.
+ 1. Return _dtf_.[[boundFormatToParts]].
+
+
+
Intl.DateTimeFormat.prototype.resolvedOptions ()