Commit 07437481 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

Fix hour cycle format

Afer the getBestPattern, replace the HhKk by the hour cycle char.
Not fix formatRange yet.

Bug: v8:9930
Change-Id: I0833539ba308d4b2f58f20ae1a137f782a82fe49
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1892126Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64691}
parent 581608a8
......@@ -924,9 +924,54 @@ icu::Calendar* CreateCalendar(Isolate* isolate, const icu::Locale& icu_locale,
return calendar_cache.Pointer()->CreateCalendar(icu_locale, tz);
}
icu::UnicodeString ReplaceHourCycleInPattern(icu::UnicodeString pattern,
Intl::HourCycle hc) {
char16_t replacement;
switch (hc) {
case Intl::HourCycle::kUndefined:
return pattern;
case Intl::HourCycle::kH11:
replacement = 'K';
break;
case Intl::HourCycle::kH12:
replacement = 'h';
break;
case Intl::HourCycle::kH23:
replacement = 'H';
break;
case Intl::HourCycle::kH24:
replacement = 'k';
break;
}
bool replace = true;
icu::UnicodeString result;
for (int32_t i = 0; i < pattern.length(); i++) {
char16_t ch = pattern.charAt(i);
switch (ch) {
case '\'':
replace = !replace;
result.append(ch);
break;
case 'H':
V8_FALLTHROUGH;
case 'h':
V8_FALLTHROUGH;
case 'K':
V8_FALLTHROUGH;
case 'k':
result.append(replace ? replacement : ch);
break;
default:
result.append(ch);
break;
}
}
return result;
}
std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormat(
const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator) {
icu::DateTimePatternGenerator* generator, Intl::HourCycle hc) {
// 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 .
......@@ -941,6 +986,7 @@ std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormat(
UErrorCode status = U_ZERO_ERROR;
pattern = generator->getBestPattern(skeleton, UDATPG_MATCH_HOUR_FIELD_LENGTH,
status);
pattern = ReplaceHourCycleInPattern(pattern, hc);
CHECK(U_SUCCESS(status));
// Make formatter from skeleton. Calendar and numbering system are added
......@@ -958,7 +1004,8 @@ class DateFormatCache {
public:
icu::SimpleDateFormat* Create(const icu::Locale& icu_locale,
const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator) {
icu::DateTimePatternGenerator* generator,
Intl::HourCycle hc) {
std::string key;
skeleton.toUTF8String<std::string>(key);
key += ":";
......@@ -974,7 +1021,7 @@ class DateFormatCache {
map_.clear();
}
std::unique_ptr<icu::SimpleDateFormat> instance(
CreateICUDateFormat(icu_locale, skeleton, generator));
CreateICUDateFormat(icu_locale, skeleton, generator, hc));
if (instance.get() == nullptr) return nullptr;
map_[key] = std::move(instance);
return static_cast<icu::SimpleDateFormat*>(map_[key]->clone());
......@@ -987,11 +1034,11 @@ class DateFormatCache {
std::unique_ptr<icu::SimpleDateFormat> CreateICUDateFormatFromCache(
const icu::Locale& icu_locale, const icu::UnicodeString& skeleton,
icu::DateTimePatternGenerator* generator) {
icu::DateTimePatternGenerator* generator, Intl::HourCycle hc) {
static base::LazyInstance<DateFormatCache>::type cache =
LAZY_INSTANCE_INITIALIZER;
return std::unique_ptr<icu::SimpleDateFormat>(
cache.Pointer()->Create(icu_locale, skeleton, generator));
cache.Pointer()->Create(icu_locale, skeleton, generator, hc));
}
icu::UnicodeString SkeletonFromDateFormat(
......@@ -1192,7 +1239,7 @@ std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern(
}
return CreateICUDateFormatFromCache(icu_locale, ReplaceSkeleton(skeleton, hc),
generator);
generator, hc);
}
class DateTimePatternGeneratorCache {
......@@ -1529,12 +1576,12 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
icu::UnicodeString skeleton_ustr(skeleton.c_str());
icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr,
generator.get());
generator.get(), hc);
if (icu_date_format.get() == nullptr) {
// Remove extensions and try again.
icu_locale = icu::Locale(icu_locale.getBaseName());
icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr,
generator.get());
generator.get(), hc);
if (icu_date_format.get() == nullptr) {
FATAL("Failed to create ICU date format, are ICU data files missing?");
}
......
// Copyright 2019 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.
let midnight = new Date(2019, 3, 4, 0);
let noon = new Date(2019, 3, 4, 12);
let df_11_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 0:00 AM", df_11_dt.format(midnight));
assertEquals("4/4/19, 0:00 PM", df_11_dt.format(noon));
let df_12_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 12:00 AM", df_12_dt.format(midnight));
assertEquals("4/4/19, 12:00 PM", df_12_dt.format(noon));
let df_23_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 00:00", df_23_dt.format(midnight));
assertEquals("4/4/19, 12:00" ,df_23_dt.format(noon));
let df_24_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 24:00", df_24_dt.format(midnight));
assertEquals("4/4/19, 12:00", df_24_dt.format(noon));
let df_11_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 午前0:00", df_11_ja_dt.format(midnight));
assertEquals("2019/04/04 午後0:00", df_11_ja_dt.format(noon));
let df_12_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 午前12:00", df_12_ja_dt.format(midnight));
assertEquals("2019/04/04 午後12:00", df_12_ja_dt.format(noon));
let df_23_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 0:00", df_23_ja_dt.format(midnight));
assertEquals("2019/04/04 12:00", df_23_ja_dt.format(noon));
let df_24_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 24:00", df_24_ja_dt.format(midnight));
assertEquals("2019/04/04 12:00", df_24_ja_dt.format(noon));
// Copyright 2019 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.
let midnight = new Date(2019, 3, 4, 0);
let noon = new Date(2019, 3, 4, 12);
let df_11 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h11"})
assertEquals("h11", df_11.resolvedOptions().hourCycle);
assertEquals("0:00 AM", df_11.formatRange(midnight, midnight));
assertEquals("0:00 PM", df_11.formatRange(noon, noon));
let df_11_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_t.resolvedOptions().hourCycle);
assertEquals("0:00 AM", df_11_t.formatRange(midnight, midnight));
assertEquals("0:00 PM", df_11_t.formatRange(noon, noon));
let df_11_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 0:00 AM", df_11_dt.formatRange(midnight, midnight));
assertEquals("4/4/19, 0:00 PM", df_11_dt.formatRange(noon, noon));
let df_12 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h12"})
assertEquals("h12", df_12.resolvedOptions().hourCycle);
assertEquals("12:00 AM", df_12.formatRange(midnight, midnight));
assertEquals("12:00 PM", df_12.formatRange(noon, noon));
let df_12_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_t.resolvedOptions().hourCycle);
assertEquals("12:00 AM", df_12_t.formatRange(midnight, midnight));
assertEquals("12:00 PM", df_12_t.formatRange(noon, noon));
let df_12_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 12:00 AM", df_12_dt.formatRange(midnight, midnight));
assertEquals("4/4/19, 12:00 PM", df_12_dt.formatRange(noon, noon));
let df_23 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h23"})
assertEquals("h23", df_23.resolvedOptions().hourCycle);
assertEquals("00:00", df_23.formatRange(midnight, midnight));
assertEquals("12:00" ,df_23.formatRange(noon, noon));
let df_23_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_t.resolvedOptions().hourCycle);
assertEquals("00:00", df_23_t.formatRange(midnight, midnight));
assertEquals("12:00" ,df_23_t.formatRange(noon, noon));
let df_23_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 00:00", df_23_dt.formatRange(midnight, midnight));
assertEquals("4/4/19, 12:00" ,df_23_dt.formatRange(noon, noon));
let df_24 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h24"})
assertEquals("h24", df_24.resolvedOptions().hourCycle);
assertEquals("24:00", df_24.formatRange(midnight, midnight));
assertEquals("12:00", df_24.formatRange(noon, noon));
let df_24_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_t.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_t.formatRange(midnight, midnight));
assertEquals("12:00", df_24_t.formatRange(noon, noon));
let df_24_dt = new Intl.DateTimeFormat(
"en", {timeStyle: "short", dateStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_dt.resolvedOptions().hourCycle);
assertEquals("4/4/19, 24:00", df_24_dt.formatRange(midnight, midnight));
assertEquals("4/4/19, 12:00", df_24_dt.formatRange(noon, noon));
let df_11_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h11"})
assertEquals("h11", df_11_ja.resolvedOptions().hourCycle);
assertEquals("午前0:00", df_11_ja.formatRange(midnight, midnight));
assertEquals("午後0:00", df_11_ja.formatRange(noon, noon));
let df_11_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_ja_t.resolvedOptions().hourCycle);
assertEquals("午前0:00", df_11_ja_t.formatRange(midnight, midnight));
assertEquals("午後0:00", df_11_ja_t.formatRange(noon, noon));
let df_11_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 午前0:00", df_11_ja_dt.formatRange(midnight, midnight));
assertEquals("2019/04/04 午後0:00", df_11_ja_dt.formatRange(noon, noon));
let df_12_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h12"})
assertEquals("h12", df_12_ja.resolvedOptions().hourCycle);
assertEquals("午前12:00", df_12_ja.formatRange(midnight, midnight));
assertEquals("午後12:00", df_12_ja.formatRange(noon, noon));
let df_12_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_ja_t.resolvedOptions().hourCycle);
assertEquals("午前12:00", df_12_ja_t.formatRange(midnight, midnight));
assertEquals("午後12:00", df_12_ja_t.formatRange(noon, noon));
let df_12_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 午前12:00", df_12_ja_dt.formatRange(midnight, midnight));
assertEquals("2019/04/04 午後12:00", df_12_ja_dt.formatRange(noon, noon));
let df_23_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h23"})
assertEquals("h23", df_23_ja.resolvedOptions().hourCycle);
assertEquals("0:00", df_23_ja.formatRange(midnight, midnight));
assertEquals("12:00", df_23_ja.formatRange(noon, noon));
let df_23_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_ja_t.resolvedOptions().hourCycle);
assertEquals("0:00", df_23_ja_t.formatRange(midnight, midnight));
assertEquals("12:00", df_23_ja_t.formatRange(noon, noon));
let df_23_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 0:00", df_23_ja_dt.formatRange(midnight, midnight));
assertEquals("2019/04/04 12:00", df_23_ja_dt.formatRange(noon, noon));
let df_24_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h24"})
assertEquals("h24", df_24_ja.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_ja.formatRange(midnight, midnight));
assertEquals("12:00", df_24_ja.formatRange(noon, noon));
let df_24_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_ja_t.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_ja_t.formatRange(midnight, midnight));
assertEquals("12:00", df_24_ja_t.formatRange(noon, noon));
let df_24_ja_dt = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", dateStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_ja_dt.resolvedOptions().hourCycle);
assertEquals("2019/04/04 24:00", df_24_ja_dt.formatRange(midnight, midnight));
assertEquals("2019/04/04 12:00", df_24_ja_dt.formatRange(noon, noon));
// Copyright 2019 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.
let midnight = new Date(2019, 3, 4, 0);
let noon = new Date(2019, 3, 4, 12);
let df_11 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h11"})
assertEquals("h11", df_11.resolvedOptions().hourCycle);
assertEquals("0:00 AM", df_11.format(midnight));
assertEquals("0:00 PM", df_11.format(noon));
let df_12 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h12"})
assertEquals("h12", df_12.resolvedOptions().hourCycle);
assertEquals("12:00 AM", df_12.format(midnight));
assertEquals("12:00 PM", df_12.format(noon));
let df_23 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h23"})
assertEquals("h23", df_23.resolvedOptions().hourCycle);
assertEquals("00:00", df_23.format(midnight));
assertEquals("12:00" ,df_23.format(noon));
let df_24 = new Intl.DateTimeFormat(
"en", {hour: "numeric", minute: "numeric", hourCycle: "h24"})
assertEquals("h24", df_24.resolvedOptions().hourCycle);
assertEquals("24:00", df_24.format(midnight));
assertEquals("12:00", df_24.format(noon));
let df_11_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h11"})
assertEquals("h11", df_11_ja.resolvedOptions().hourCycle);
assertEquals("午前0:00", df_11_ja.format(midnight));
assertEquals("午後0:00", df_11_ja.format(noon));
let df_12_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h12"})
assertEquals("h12", df_12_ja.resolvedOptions().hourCycle);
assertEquals("午前12:00", df_12_ja.format(midnight));
assertEquals("午後12:00", df_12_ja.format(noon));
let df_23_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h23"})
assertEquals("h23", df_23_ja.resolvedOptions().hourCycle);
assertEquals("0:00", df_23_ja.format(midnight));
assertEquals("12:00", df_23_ja.format(noon));
let df_24_ja = new Intl.DateTimeFormat(
"ja-JP", {hour: "numeric", minute: "numeric", hourCycle: "h24"})
assertEquals("h24", df_24_ja.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_ja.format(midnight));
assertEquals("12:00", df_24_ja.format(noon));
// Copyright 2019 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.
let midnight = new Date(2019, 3, 4, 0);
let noon = new Date(2019, 3, 4, 12);
let df_11_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_t.resolvedOptions().hourCycle);
assertEquals("0:00 AM", df_11_t.format(midnight));
assertEquals("0:00 PM", df_11_t.format(noon));
let df_12_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_t.resolvedOptions().hourCycle);
assertEquals("12:00 AM", df_12_t.format(midnight));
assertEquals("12:00 PM", df_12_t.format(noon));
let df_23_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_t.resolvedOptions().hourCycle);
assertEquals("00:00", df_23_t.format(midnight));
assertEquals("12:00" ,df_23_t.format(noon));
let df_24_t = new Intl.DateTimeFormat(
"en", {timeStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_t.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_t.format(midnight));
assertEquals("12:00", df_24_t.format(noon));
let df_11_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h11"})
assertEquals("h11", df_11_ja_t.resolvedOptions().hourCycle);
assertEquals("午前0:00", df_11_ja_t.format(midnight));
assertEquals("午後0:00", df_11_ja_t.format(noon));
let df_12_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h12"})
assertEquals("h12", df_12_ja_t.resolvedOptions().hourCycle);
assertEquals("午前12:00", df_12_ja_t.format(midnight));
assertEquals("午後12:00", df_12_ja_t.format(noon));
let df_23_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h23"})
assertEquals("h23", df_23_ja_t.resolvedOptions().hourCycle);
assertEquals("0:00", df_23_ja_t.format(midnight));
assertEquals("12:00", df_23_ja_t.format(noon));
let df_24_ja_t = new Intl.DateTimeFormat(
"ja-JP", {timeStyle: "short", hourCycle: "h24"})
assertEquals("h24", df_24_ja_t.resolvedOptions().hourCycle);
assertEquals("24:00", df_24_ja_t.format(midnight));
assertEquals("12:00", df_24_ja_t.format(noon));
......@@ -41,6 +41,8 @@
'number-format/unified/notation-engineering-formatToParts': [PASS, FAIL],
'number-format/unified/notation-scientific-formatToParts': [PASS, FAIL],
# http://crbug/v8/9930
'date-format/format_range_hour_cycle': [FAIL],
}], # ALWAYS
['variant == no_wasm_traps', {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment