Open Bug 1817626 Opened 1 year ago Updated 1 year ago

formatToParts returns 2-digit for month instead of numeric

Categories

(Core :: JavaScript: Internationalization API, defect, P3)

Firefox 110
defect

Tracking

()

UNCONFIRMED

People

(Reporter: edwin, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/110.0

Steps to reproduce:

Type this in the Firefox Console:

const date = new Date("2013-03-24T10:11:16.000Z")

dateTimeFormat = new Intl.DateTimeFormat('en-GB', { month: 'numeric', year: 'numeric'})

dateTimeFormat.formatToParts(date)

Unfold the result

Actual results:

You'll see this:

0: Object { type: "month", value: "03" }

1: Object { type: "literal", value: "/" }

2: Object { type: "year", value: "2013" }

Expected results:

It should be this:

0: Object { type: "month", value: "3" }

1: Object { type: "literal", value: "/" }

2: Object { type: "year", value: "2013" }

The month result should be "3" instead of "03".

So month was requested to give a representation of "numeric", but the result was shown as different representation, namely "2-digit".

It works fine when year is not requested to give a representation.

Chrome also gives the month as "03".

Component: Untriaged → JavaScript: Internationalization API
Product: Firefox → Core
Blocks: sm-runtime
Severity: -- → S3
Priority: -- → P3

This happens because the underlying CLDR resources explicitly define that the two-digit format should be used when requesting the format "yM". (The date format pattern syntax is defined in https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns.)

André Bargull: do you mean to say the the result should be "03" because of CLDR or do you mean to say the Intl implementation is using CLDR incorrectly?

The Intl.DateTimeFormat.prototype.format behavior is specified here:
https://402.ecma-international.org/1.0/#sec-12.3.2

Here, we read

  1. Let nf be the result of creating a new NumberFormat object as if by the expression new Intl.NumberFormat([locale], {useGrouping: false}) where Intl.NumberFormat is the standard built-in constructor defined in 11.1.3.

  2. vii. If f is "numeric", then
    Let fv be the result of calling the FormatNumber abstract operation (defined in 11.3.2) with arguments nf and v.

Note that in point 3., the "minimumIntegerDigits: 2" is absent and FormatNumber.format() returns "3" instead of "03". Al least, that's how I interpret this.

(In reply to Edwin Martin from comment #3)

André Bargull: do you mean to say the the result should be "03" because of CLDR or do you mean to say the Intl implementation is using CLDR incorrectly?

The result should be "03" because of CLDR.

The Intl.DateTimeFormat.prototype.format behavior is specified here:
https://402.ecma-international.org/1.0/#sec-12.3.2
[...]
Note that in point 3., the "minimumIntegerDigits: 2" is absent and FormatNumber.format() returns "3" instead of "03". Al least, that's how I interpret this.

The user-requested format isn't directly used in FormatDateTimePattern. There's actually an earlier step within the Intl.DateTimeFormat constructor to map the user-requested format to a different format pattern: In InitializeDateTimeFormat, the user-requested format is processed and stored in the formatOptions variable. formatOptions is then passed to either BasicFormatMatcher or BestFitFormatMatcher, where formatOptions is mapped to a pattern supported by the platform. This is where the CLDR data comes into play and the format "yM" is mapped into the pattern string "MM/y". The resolved pattern has the format {year: "numeric", month: "2-digit"}, which is then later processed by the FormatDateTimePattern operation.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: