Use the base locale when getting the best match pattern

This is to fix an assertion failure in formatToParts when
Chinese calendar is specified with 'u-ca-chinese'.

See https://github.com/tc39/ecma402/issues/225 . This CL
is a temporary work-around to get v8 match the spec in terms
of the external behavior, but it's not taking the steps in
the spec, yet.

Moreover, the spec may have to be revised as to how to pick the best
match pattern when the default calendar for a locale is different from
the calendar specified via 'u-ca'. How to handle 'related year' part
also needs to be specified.

Bug: chromium:826549
Test: intl/date-format/format-with-extensions
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I1f9a2467e86e71e024bc9babe18f16e49746008e
Reviewed-on: https://chromium-review.googlesource.com/1006915
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jungshik Shin <jshin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52556}
This commit is contained in:
Jungshik Shin 2018-04-11 16:40:37 -07:00 committed by Commit Bot
parent 2b24df9929
commit 98c0cd9f8f
2 changed files with 74 additions and 1 deletions

View File

@ -123,8 +123,20 @@ icu::SimpleDateFormat* CreateICUDateFormat(Isolate* isolate,
icu::SimpleDateFormat* date_format = nullptr;
icu::UnicodeString skeleton;
if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
// See https://github.com/tc39/ecma402/issues/225 . The best pattern
// generation needs to be done in the base locale according to the
// current spec however odd it may be. See also crbug.com/826549 .
// This is a temporary work-around to get v8's external behavior to match
// the current spec, but does not follow the spec provisions mentioned
// in the above Ecma 402 issue.
// TODO(jshin): The spec may need to be revised because using the base
// locale for the pattern match is not quite right. Moreover, what to
// do with 'related year' part when 'chinese/dangi' calendar is specified
// has to be discussed. Revisit once the spec is clarified/revised.
icu::Locale no_extension_locale(icu_locale.getBaseName());
std::unique_ptr<icu::DateTimePatternGenerator> generator(
icu::DateTimePatternGenerator::createInstance(icu_locale, status));
icu::DateTimePatternGenerator::createInstance(no_extension_locale,
status));
icu::UnicodeString pattern;
if (U_SUCCESS(status))
pattern = generator->getBestPattern(skeleton, status);

View File

@ -0,0 +1,61 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const d = new Date(2018, 5, 21); // 2018-06-21
function checkFormat(locale, options, expected) {
let df = new Intl.DateTimeFormat(locale, options);
let resolvedOptions = df.resolvedOptions();
assertEquals(expected.cal, resolvedOptions.calendar);
assertEquals(expected.numSys, resolvedOptions.numberingSystem);
let formattedParts = df.formatToParts(d);
let formattedReconstructedFromParts = formattedParts.map((part) => part.value)
.reduce((accumulated, part) => accumulated + part);
let formatted = df.format(d);
assertEquals(formatted, formattedReconstructedFromParts);
assertEquals(expected.types, formattedParts.map((part) => part.type));
assertEquals(expected.formatted, formatted);
}
// Even though the calendar is Chinese, the best pattern search for formatting
// should be done in the base locale (i.e. en or en-GB instead of
// en-u-ca-chinese or en-GB-u-ca-chinese). Otherwise, {year: 'numeric'} would
// results in '35 (wu-su)' where 'wu-su' is the designation for year 35 in the
// 60-year cycle. See https://github.com/tc39/ecma402/issues/225 .
[
["en", "gregory", "latn", "2018"],
["en-GB", "gregory", "latn", "2018"],
["en-u-ca-chinese", "chinese", "latn", "35"],
["en-GB-u-ca-chinese", "chinese", "latn", "35"],
["en-u-ca-chinese-nu-deva", "chinese", "deva", "३५"],
["en-GB-u-ca-chinese-nu-deva", "chinese", "deva", "३५"],
].forEach(function(entry) {
checkFormat(entry[0], {year: 'numeric'},
{ cal: entry[1],
numSys: entry[2],
formatted: entry[3],
types: ["year"],
});
});
const enUSTypes = ["month", "literal", "day", "literal", "year"];
const enGBTypes = ["day", "literal", "month", "literal", "year"];
[
["en", "gregory", "latn", "6/21/2018", enUSTypes],
["en-GB", "gregory", "latn", "21/06/2018", enGBTypes],
["en-u-nu-deva", "gregory", "deva", "६/२१/२०१८", enUSTypes],
["en-u-ca-chinese", "chinese", "latn", "5/8/35", enUSTypes],
["en-GB-u-ca-chinese", "chinese", "latn", "08/05/35", enGBTypes],
["en-u-ca-chinese-nu-deva", "chinese", "deva", "५/८/३५", enUSTypes],
].forEach(function(entry) {
checkFormat(entry[0], {},
{ cal: entry[1],
numSys: entry[2],
formatted: entry[3],
types: entry[4],
});
});