Skip to content
This repository was archived by the owner on Apr 14, 2021. It is now read-only.

1.1.0 has issues with Intl.DateTimeFormat #152

Closed
ericf opened this issue Mar 1, 2016 · 11 comments · May be fixed by godaddy/external#6
Closed

1.1.0 has issues with Intl.DateTimeFormat #152

ericf opened this issue Mar 1, 2016 · 11 comments · May be fixed by godaddy/external#6
Assignees
Labels

Comments

@ericf
Copy link
Collaborator

ericf commented Mar 1, 2016

I noticed that 1.1.0 isn't properly formatting times, when the minutes are less than 10 the leading 0 is missing; e.g.,

var nf = new Intl.DateTimeFormat('en', {
  hour: 'numeric',
  minute: 'numeric'
});

var date = new Date(1456859319008);
console.log(nf.format(date)); // "2:8 PM"
ericf added a commit to ericf/react-intl that referenced this issue Mar 1, 2016
@caridy caridy self-assigned this Mar 1, 2016
@caridy caridy added the bug label Mar 1, 2016
@caridy
Copy link
Collaborator

caridy commented Mar 1, 2016

Yeah, I figure this was going to be a problem. 1.1.0 fixes a bunch of issues when the options are overruling the best fit options, but that introduces this problem. The resolution is to follow CLDR rules for the closest distance, in which case, the fact that for certain locales, the options from the example above will produce pattern: Hm {am}, where numeric hours is not at closest distance to H and therefor it can't be overruled. I plan to work on this in the next couple of days.

Note: this most likely solve many of the remaining issues with datatime format.

@ericf
Copy link
Collaborator Author

ericf commented Mar 1, 2016

I know this is tricky and ambiguous as to what browsers do when handling the formatting options — it's clear they are simply calling into ICU.

The reason I'm setting hour and minute to "numeric" is that it's more broad than "2-digit", which allows the impl to choose the best fit for the locale; e.g., what should this render at 2pm: "en-US" with hour: "2-digit", minute: "2-digit", hour12: true, "2:00 PM" or "02:00 PM". While the latter matches the "2-digit" option, the former is what you'd expect because it's colloquially US English.

The problem is these edge cases are locale specific, so for browsers' current impls they choose what's colloquial for the locale over the explicit options. Unless ECMA 402 tightens this aspect of the spec, I think the polyfill should behave the same — hopefully this doesn't mean we have to code in a bunch of exceptions per locale :-/

@caridy
Copy link
Collaborator

caridy commented Mar 1, 2016

@ericf that's correct! the error here is that Intl.js was implementing an strict BasicFormatMatcher(), while in 1.1 I have relaxed that a little bit, and in the upcoming release, I will actually make that BestFitMatcher() so we have the freedom to do what we please to match existing implementations. All browsers are implementing BestFitMatcher() today. Once I do that, I can add the pieces to take into consideration the "closest distance" computations before blindly overrule the options. I will keep you posted.

@caridy
Copy link
Collaborator

caridy commented Mar 1, 2016

btw, this is related to this tc39/ecma402#58

@ericf
Copy link
Collaborator Author

ericf commented Apr 26, 2016

@caridy and I discussed this at length and figure out the issue which is was how the options passed to Intl.DateTimeFormat are used to generated the formatted string produced by format(). What we came to is the process should work like this:

options → skeleton → format pattern

The user-specified options passed to Intl.DateTimeFormat are used to select a format pattern based on the skeleton keys. The corresponding format pattern encodes the position of the parts and how they should be formatted. i.e., the options don't dictate the way parts are formatted, the format pattern we get from CLDR does.

English Example:

let df = new Intl.DateTimeFormat('en', {month: 'long'});
console.log(df.format(Date.now())); // "April"
{month: "long"} → "MMM" → "LLL"

Japanese Example:

let df = new Intl.DateTimeFormat('ja', {month: 'long'});
console.log(df.format(Date.now())); // "4月"
{month: "long"} → "MMM" → "M月"

Note: How the user-specified option of {month: 'long'} corresponds to the same skeleton key for English and Japanese, but the corresponding format pattern for Japanese uses a numeric month format, and not a string-based month name like English. This shows how the options don't imply the actual formatting which is applied to each part in the format pattern, rather the pattern itself encodes this.

This means that when we process/expand the format patterns we have to do so in a non-lossy way so that we retain the information about how to format each part of the pattern.

@jpresley23
Copy link

Is there a workaround for this? I'm running an issue where we use react-intl but I need Intl.js polyfill for PhantomJS for our tests. If I use Intl.js version 1.1.0, the leading zero in the minutes is dropped off. If I use 1.0.1, the leading 0 for "00:00" is dropped (it's rendered as "0:00").

@caridy
Copy link
Collaborator

caridy commented May 12, 2016

I'm planning to release 1.2 tomorrow :)

@caridy
Copy link
Collaborator

caridy commented May 12, 2016

fixed by #171

@JamieMason
Copy link

JamieMason commented May 13, 2016

Similar can be demonstrated here;

var Intl = require("intl")

new Intl.DateTimeFormat('en-GB', {
  hour: '2-digit',
  hour12: false,
  minute: 'numeric'
}).format(new Date(1983, 9, 13));

https://tonicdev.com/5735aba53ed13c11004b5696/5735aba53ed13c11004b5697

should be 00:00 but is 00:0


EDIT

Last version that worked was 1.0.1;

var Intl = require("intl@1.0.1")

new Intl.DateTimeFormat('en-GB', {
  hour: '2-digit',
  hour12: false,
  minute: 'numeric'
}).format(new Date(1983, 9, 13));

https://tonicdev.com/5735aba53ed13c11004b5696/5735ad8dfba2ae1200967830


EDIT 2

...but that shows 0:00 rather than 00:00

@Delagen
Copy link

Delagen commented May 23, 2016

1.2.3 version still does not solve it ((

@caridy
Copy link
Collaborator

caridy commented Sep 20, 2016

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants