Chromium Code Reviews| Index: src/i18n.cc |
| diff --git a/src/i18n.cc b/src/i18n.cc |
| index d2245ef34a9a319a53b4cf4b4ea05ec095fef2d5..30d649e45c95977047b7092034b0c80b62518e78 100644 |
| --- a/src/i18n.cc |
| +++ b/src/i18n.cc |
| @@ -899,5 +899,87 @@ void V8BreakIterator::DeleteBreakIterator( |
| GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter())); |
| } |
| +ICUTimezoneCache::ICUTimezoneCache() { Clear(); } |
|
jgruber
2017/03/03 08:35:29
I'm surprised this doesn't fail. Clear() deletes t
Dan Ehrenberg
2017/03/03 13:20:27
Wow, not sure how I got this so wrong; I guess I s
|
| + |
| +ICUTimezoneCache::~ICUTimezoneCache() { Clear(); } |
| + |
| +const char* ICUTimezoneCache::LocalTimezone(double time_ms) { |
| + bool is_dst = DaylightSavingsOffset(time_ms) != 0; |
| + char* name = is_dst ? dst_timezone_name_ : timezone_name_; |
|
jgruber
2017/03/03 08:35:29
The cache is never filled, not sure if that's on p
Dan Ehrenberg
2017/03/03 13:20:27
What do you mean? Why is it never filled? I though
jgruber
2017/03/03 13:29:08
Yup you're right. Sorry, my mistake.
|
| + if (name[0] == '\0') { |
| + icu::UnicodeString result; |
| + GetTimeZone()->getDisplayName(is_dst, icu::TimeZone::SHORT, result); |
| + |
| + // With the SHORT format and the default locale, the result should be of |
| + // the form PST or CET, short and within ASCII range. |
| + int32_t length = result.length(); |
| + CHECK(length < kMaxTimezoneChars); |
| + for (int32_t i = 0; i < length; i++) { |
| + UChar ch = result[i]; |
| + CHECK(ch == static_cast<UChar>(static_cast<char>(ch))); |
| + name[i] = static_cast<char>(ch); |
| + } |
| + name[length] = '\0'; |
| + } |
| + return const_cast<const char*>(name); |
| +} |
| + |
| +icu::TimeZone* ICUTimezoneCache::GetTimeZone() { |
| + if (timezone_ == nullptr) { |
| + timezone_ = icu::TimeZone::createDefault(); |
| + } |
| + return timezone_; |
| +} |
| + |
| +bool ICUTimezoneCache::GetOffsets(double time_ms, int32_t* raw_offset, |
| + int32_t* dst_offset) { |
| + UErrorCode status = U_ZERO_ERROR; |
| + GetTimeZone()->getOffset(time_ms, false, *raw_offset, *dst_offset, status); |
| + if (!U_SUCCESS(status)) return false; |
|
jgruber
2017/03/03 08:35:29
Nit: return U_SUCCESS(status)
Dan Ehrenberg
2017/03/03 13:20:27
Done, but I would be interested in more feedback h
|
| + return true; |
| +} |
| + |
| +double ICUTimezoneCache::DaylightSavingsOffset(double time_ms) { |
| + int32_t raw_offset, dst_offset; |
| + if (!GetOffsets(time_ms, &raw_offset, &dst_offset)) return 0; |
| + return dst_offset; |
| +} |
| + |
| +double ICUTimezoneCache::LocalTimeOffset() { |
| + int32_t raw_offset, dst_offset; |
| + if (!GetOffsets(icu::Calendar::getNow(), &raw_offset, &dst_offset)) return 0; |
| + return raw_offset; |
| +} |
| + |
| +void ICUTimezoneCache::Clear() { |
| + delete timezone_; |
| + timezone_ = nullptr; |
| + timezone_name_[0] = '\0'; |
| + dst_timezone_name_[0] = '\0'; |
| +} |
| + |
| +ICUOSTimezoneCache::ICUOSTimezoneCache() : os_tz_cache_(nullptr) {} |
| + |
| +ICUOSTimezoneCache::~ICUOSTimezoneCache() { delete os_tz_cache_; } |
| + |
| +const char* ICUOSTimezoneCache::LocalTimezone(double time_ms) { |
| + const char* result = ICUTimezoneCache::LocalTimezone(time_ms); |
| + // ICU often returns timezones which are not as descriptive as they |
| + // could be, e.g., GMT+1 for Europe/Madrid when in en_US. When a timezone |
| + // starts with GMT, call out to the OS to get the 'real' name. |
|
ulan
2017/03/03 13:20:27
This seems hacky as it breaks the "cache" semantic
Dan Ehrenberg
2017/03/03 15:06:54
I agree that it's hacky, but I'm not sure we'll ge
|
| + if (result[0] == 'G' && result[1] == 'M' && result[2] == 'T') { |
|
jgruber
2017/03/03 08:35:29
Nit: Another option would be to use strncmp.
Dan Ehrenberg
2017/03/03 13:20:27
Done.
|
| + if (os_tz_cache_ == nullptr) { |
| + os_tz_cache_ = base::OS::CreateTimezoneCache(); |
| + } |
| + return os_tz_cache_->LocalTimezone(time_ms); |
| + } |
| + return result; |
| +} |
| + |
| +void ICUOSTimezoneCache::Clear() { |
| + ICUTimezoneCache::Clear(); |
| + if (os_tz_cache_) os_tz_cache_->Clear(); |
| +} |
| + |
| } // namespace internal |
| } // namespace v8 |