Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/js-date-time-format.cc')
-rw-r--r--deps/v8/src/objects/js-date-time-format.cc214
1 files changed, 149 insertions, 65 deletions
diff --git a/deps/v8/src/objects/js-date-time-format.cc b/deps/v8/src/objects/js-date-time-format.cc
index 5643ee57d57..669dfd88ab2 100644
--- a/deps/v8/src/objects/js-date-time-format.cc
+++ b/deps/v8/src/objects/js-date-time-format.cc
@@ -34,6 +34,23 @@ namespace internal {
namespace {
+std::string ToHourCycleString(JSDateTimeFormat::HourCycle hc) {
+ switch (hc) {
+ case JSDateTimeFormat::HourCycle::kH11:
+ return "h11";
+ case JSDateTimeFormat::HourCycle::kH12:
+ return "h12";
+ case JSDateTimeFormat::HourCycle::kH23:
+ return "h23";
+ case JSDateTimeFormat::HourCycle::kH24:
+ return "h24";
+ case JSDateTimeFormat::HourCycle::kUndefined:
+ return "";
+ default:
+ UNREACHABLE();
+ }
+}
+
JSDateTimeFormat::HourCycle ToHourCycle(const std::string& hc) {
if (hc == "h11") return JSDateTimeFormat::HourCycle::kH11;
if (hc == "h12") return JSDateTimeFormat::HourCycle::kH12;
@@ -261,7 +278,7 @@ const std::vector<PatternData>& GetPatternData(
}
}
-std::string GetGMTTzID(Isolate* isolate, const std::string& input) {
+std::string GetGMTTzID(const std::string& input) {
std::string ret = "Etc/GMT";
switch (input.length()) {
case 8:
@@ -304,10 +321,8 @@ char LocaleIndependentAsciiToLower(char ch) {
// or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only
// deals with ASCII only characters.
// 'of', 'au' and 'es' are special-cased and lowercased.
-// Also "Antarctica/DumontDUrville" is special case.
// ICU's timezone parsing is case sensitive, but ECMAScript is case insensitive
-std::string ToTitleCaseTimezoneLocation(Isolate* isolate,
- const std::string& input) {
+std::string ToTitleCaseTimezoneLocation(const std::string& input) {
std::string title_cased;
int word_length = 0;
for (char ch : input) {
@@ -332,34 +347,102 @@ std::string ToTitleCaseTimezoneLocation(Isolate* isolate,
return std::string();
}
}
- // Special case
- if (title_cased == "Antarctica/Dumontdurville") {
- return "Antarctica/DumontDUrville";
- }
+
return title_cased;
}
+class SpecialTimeZoneMap {
+ public:
+ SpecialTimeZoneMap() {
+ Add("America/Argentina/ComodRivadavia");
+ Add("America/Knox_IN");
+ Add("Antarctica/McMurdo");
+ Add("Australia/ACT");
+ Add("Australia/LHI");
+ Add("Australia/NSW");
+ Add("Antarctica/DumontDUrville");
+ Add("Brazil/DeNoronha");
+ Add("CET");
+ Add("CST6CDT");
+ Add("Chile/EasterIsland");
+ Add("EET");
+ Add("EST");
+ Add("EST5EDT");
+ Add("GB");
+ Add("GB-Eire");
+ Add("HST");
+ Add("MET");
+ Add("MST");
+ Add("MST7MDT");
+ Add("Mexico/BajaNorte");
+ Add("Mexico/BajaSur");
+ Add("NZ");
+ Add("NZ-CHAT");
+ Add("PRC");
+ Add("PST8PDT");
+ Add("ROC");
+ Add("ROK");
+ Add("UCT");
+ Add("W-SU");
+ Add("WET");
+ }
+
+ std::string Find(const std::string& id) {
+ auto it = map_.find(id);
+ if (it != map_.end()) {
+ return it->second;
+ }
+ return "";
+ }
+
+ private:
+ void Add(const char* id) {
+ std::string upper(id);
+ transform(upper.begin(), upper.end(), upper.begin(),
+ LocaleIndependentAsciiToUpper);
+ map_.insert({upper, id});
+ }
+ std::map<std::string, std::string> map_;
+};
+
// Return the time zone id which match ICU's expectation of title casing
// return empty string when error.
-std::string CanonicalizeTimeZoneID(Isolate* isolate, const std::string& input) {
+std::string CanonicalizeTimeZoneID(const std::string& input) {
std::string upper = input;
transform(upper.begin(), upper.end(), upper.begin(),
LocaleIndependentAsciiToUpper);
- if (upper == "UTC" || upper == "GMT" || upper == "ETC/UTC" ||
- upper == "ETC/GMT") {
- return "UTC";
+ if (upper.length() >= 3) {
+ if (memcmp(upper.c_str(), "ETC", 3) == 0) {
+ if (upper == "ETC/UTC" || upper == "ETC/GMT" || upper == "ETC/UCT") {
+ return "UTC";
+ }
+ if (strncmp(upper.c_str(), "ETC/GMT", 7) == 0) {
+ return GetGMTTzID(input);
+ }
+ } else if (memcmp(upper.c_str(), "GMT", 3) == 0) {
+ if (upper == "GMT" || upper == "GMT0" || upper == "GMT+0" ||
+ upper == "GMT-0") {
+ return "UTC";
+ }
+ } else if (memcmp(upper.c_str(), "US/", 3) == 0) {
+ std::string title = ToTitleCaseTimezoneLocation(input);
+ // Change "Us/" to "US/"
+ title[1] = 'S';
+ return title;
+ } else if (upper == "UTC") {
+ return "UTC";
+ }
}
// We expect only _, '-' and / beside ASCII letters.
- // All inputs should conform to Area/Location(/Location)*, or Etc/GMT* .
- // TODO(jshin): 1. Support 'GB-Eire", 'EST5EDT", "ROK', 'US/*', 'NZ' and many
- // other aliases/linked names when moving timezone validation code to C++.
- // See crbug.com/364374 and crbug.com/v8/8007 .
- // 2. Resolve the difference betwee CLDR/ICU and IANA time zone db.
- // See http://unicode.org/cldr/trac/ticket/9892 and crbug.com/645807 .
- if (strncmp(upper.c_str(), "ETC/GMT", 7) == 0) {
- return GetGMTTzID(isolate, input);
- }
- return ToTitleCaseTimezoneLocation(isolate, input);
+
+ static base::LazyInstance<SpecialTimeZoneMap>::type special_time_zone_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+ std::string special_case = special_time_zone_map.Pointer()->Find(upper);
+ if (!special_case.empty()) {
+ return special_case;
+ }
+ return ToTitleCaseTimezoneLocation(input);
}
Handle<String> DateTimeStyleAsString(Isolate* isolate,
@@ -479,6 +562,7 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
// [[Minute]] "minute"
// [[Second]] "second"
// [[TimeZoneName]] "timeZoneName"
+ // [[FractionalSecondDigits]] "fractionalSecondDigits"
CHECK(JSReceiver::CreateDataProperty(isolate, options,
factory->locale_string(), locale,
Just(kDontThrow))
@@ -549,6 +633,13 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
}
}
}
+ if (FLAG_harmony_intl_dateformat_fractional_second_digits) {
+ int fsd = FractionalSecondDigitsFromPattern(pattern);
+ CHECK(JSReceiver::CreateDataProperty(
+ isolate, options, factory->fractionalSecondDigits_string(),
+ factory->NewNumberFromInt(fsd), Just(kDontThrow))
+ .FromJust());
+ }
}
// dateStyle
@@ -568,14 +659,6 @@ MaybeHandle<JSObject> JSDateTimeFormat::ResolvedOptions(
Just(kDontThrow))
.FromJust());
}
- if (FLAG_harmony_intl_dateformat_fractional_second_digits) {
- int fsd = FractionalSecondDigitsFromPattern(pattern);
- CHECK(JSReceiver::CreateDataProperty(
- isolate, options, factory->fractionalSecondDigits_string(),
- factory->NewNumberFromInt(fsd), Just(kDontThrow))
- .FromJust());
- }
-
return options;
}
@@ -868,15 +951,14 @@ bool IsValidTimeZoneName(const icu::TimeZone& tz) {
canonical != icu::UnicodeString("Etc/Unknown", -1, US_INV);
}
-std::unique_ptr<icu::TimeZone> CreateTimeZone(Isolate* isolate,
- const char* timezone) {
+std::unique_ptr<icu::TimeZone> CreateTimeZone(const char* timezone) {
// Create time zone as specified by the user. We have to re-create time zone
// since calendar takes ownership.
if (timezone == nullptr) {
// 19.a. Else / Let timeZone be DefaultTimeZone().
return std::unique_ptr<icu::TimeZone>(icu::TimeZone::createDefault());
}
- std::string canonicalized = CanonicalizeTimeZoneID(isolate, timezone);
+ std::string canonicalized = CanonicalizeTimeZoneID(timezone);
if (canonicalized.empty()) return std::unique_ptr<icu::TimeZone>();
std::unique_ptr<icu::TimeZone> tz(
icu::TimeZone::createTimeZone(canonicalized.c_str()));
@@ -1078,10 +1160,18 @@ icu::DateIntervalFormat* LazyCreateDateIntervalFormat(
icu::SimpleDateFormat* icu_simple_date_format =
date_time_format->icu_simple_date_format().raw();
UErrorCode status = U_ZERO_ERROR;
+
+ icu::Locale loc = *(date_time_format->icu_locale().raw());
+ // We need to pass in the hc to DateIntervalFormat by using Unicode 'hc'
+ // extension.
+ std::string hcString = ToHourCycleString(date_time_format->hour_cycle());
+ if (!hcString.empty()) {
+ loc.setUnicodeKeywordValue("hc", hcString, status);
+ }
+
std::unique_ptr<icu::DateIntervalFormat> date_interval_format(
icu::DateIntervalFormat::createInstance(
- SkeletonFromDateFormat(*icu_simple_date_format),
- *(date_time_format->icu_locale().raw()), status));
+ SkeletonFromDateFormat(*icu_simple_date_format), loc, status));
if (U_FAILURE(status)) {
return nullptr;
}
@@ -1262,17 +1352,15 @@ class DateTimePatternGeneratorCache {
public:
// Return a clone copy that the caller have to free.
icu::DateTimePatternGenerator* CreateGenerator(const icu::Locale& locale) {
- std::string key(FLAG_harmony_intl_other_calendars ? locale.getName()
- : locale.getBaseName());
+ std::string key(locale.getName());
base::MutexGuard guard(&mutex_);
auto it = map_.find(key);
if (it != map_.end()) {
return it->second->clone();
}
UErrorCode status = U_ZERO_ERROR;
- map_[key].reset(icu::DateTimePatternGenerator::createInstance(
- FLAG_harmony_intl_other_calendars ? locale : icu::Locale(key.c_str()),
- status));
+ map_[key].reset(
+ icu::DateTimePatternGenerator::createInstance(locale, status));
// Fallback to use "root".
if (U_FAILURE(status)) {
status = U_ZERO_ERROR;
@@ -1321,32 +1409,29 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
std::unique_ptr<char[]> calendar_str = nullptr;
std::unique_ptr<char[]> numbering_system_str = nullptr;
- if (FLAG_harmony_intl_add_calendar_numbering_system) {
- const std::vector<const char*> empty_values = {};
- // 6. Let calendar be ? GetOption(options, "calendar",
- // "string", undefined, undefined).
- Maybe<bool> maybe_calendar = Intl::GetStringOption(
- isolate, options, "calendar", empty_values, service, &calendar_str);
- MAYBE_RETURN(maybe_calendar, MaybeHandle<JSDateTimeFormat>());
- if (maybe_calendar.FromJust() && calendar_str != nullptr) {
- icu::Locale default_locale;
- if (!Intl::IsWellFormedCalendar(calendar_str.get())) {
- THROW_NEW_ERROR(
- isolate,
- NewRangeError(
- MessageTemplate::kInvalid, factory->calendar_string(),
- factory->NewStringFromAsciiChecked(calendar_str.get())),
- JSDateTimeFormat);
- }
+ const std::vector<const char*> empty_values = {};
+ // 6. Let calendar be ? GetOption(options, "calendar",
+ // "string", undefined, undefined).
+ Maybe<bool> maybe_calendar = Intl::GetStringOption(
+ isolate, options, "calendar", empty_values, service, &calendar_str);
+ MAYBE_RETURN(maybe_calendar, MaybeHandle<JSDateTimeFormat>());
+ if (maybe_calendar.FromJust() && calendar_str != nullptr) {
+ icu::Locale default_locale;
+ if (!Intl::IsWellFormedCalendar(calendar_str.get())) {
+ THROW_NEW_ERROR(
+ isolate,
+ NewRangeError(MessageTemplate::kInvalid, factory->calendar_string(),
+ factory->NewStringFromAsciiChecked(calendar_str.get())),
+ JSDateTimeFormat);
}
-
- // 8. Let numberingSystem be ? GetOption(options, "numberingSystem",
- // "string", undefined, undefined).
- Maybe<bool> maybe_numberingSystem = Intl::GetNumberingSystem(
- isolate, options, service, &numbering_system_str);
- MAYBE_RETURN(maybe_numberingSystem, MaybeHandle<JSDateTimeFormat>());
}
+ // 8. Let numberingSystem be ? GetOption(options, "numberingSystem",
+ // "string", undefined, undefined).
+ Maybe<bool> maybe_numberingSystem = Intl::GetNumberingSystem(
+ isolate, options, service, &numbering_system_str);
+ MAYBE_RETURN(maybe_numberingSystem, MaybeHandle<JSDateTimeFormat>());
+
// 6. Let hour12 be ? GetOption(options, "hour12", "boolean", undefined,
// undefined).
bool hour12;
@@ -1424,13 +1509,12 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New(
}
// 17. Let timeZone be ? Get(options, "timeZone").
- const std::vector<const char*> empty_values;
std::unique_ptr<char[]> timezone = nullptr;
Maybe<bool> maybe_timezone = Intl::GetStringOption(
isolate, options, "timeZone", empty_values, service, &timezone);
MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>());
- std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(isolate, timezone.get());
+ std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(timezone.get());
if (tz.get() == nullptr) {
THROW_NEW_ERROR(
isolate,