зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1731620 - Part 6: Add default time zone setters to mozila::intl::TimeZone. r=platform-i18n-reviewers,gregtatum
Add setters to change ICU's default time zone. 1. `SetDefaultTimeZone()` sets the default time zone from a time zone identifier. 2. `SetDefaultTimeZoneFromHostTimeZone()` synchronizes the default time zone with the host system's time zone. The two new methods will be used in the next part to replace ICU calls in `js::DateTimeInfo::internalResyncICUDefaultTimeZone()`. Differential Revision: https://phabricator.services.mozilla.com/D126196
This commit is contained in:
Родитель
0d2aefce15
Коммит
f0ef6836c5
|
@ -4,6 +4,11 @@
|
|||
|
||||
#include "mozilla/intl/TimeZone.h"
|
||||
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
#include "unicode/uenum.h"
|
||||
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
|
||||
# include "unicode/basictz.h"
|
||||
|
@ -208,6 +213,97 @@ Result<int32_t, ICUError> TimeZone::GetUTCOffsetMs(int64_t aLocalMilliseconds) {
|
|||
#endif
|
||||
}
|
||||
|
||||
using TimeZoneIdentifierVector =
|
||||
Vector<char16_t, TimeZone::TimeZoneIdentifierLength>;
|
||||
|
||||
#if !MOZ_INTL_USE_ICU_CPP_TIMEZONE
|
||||
static bool IsUnknownTimeZone(const TimeZoneIdentifierVector& timeZone) {
|
||||
constexpr std::string_view unknownTimeZone = UCAL_UNKNOWN_ZONE_ID;
|
||||
|
||||
return timeZone.length() == unknownTimeZone.length() &&
|
||||
std::equal(timeZone.begin(), timeZone.end(), unknownTimeZone.begin(),
|
||||
unknownTimeZone.end());
|
||||
}
|
||||
|
||||
static ICUResult SetDefaultTimeZone(TimeZoneIdentifierVector& timeZone) {
|
||||
// The string mustn't already be null-terminated.
|
||||
MOZ_ASSERT_IF(!timeZone.empty(), timeZone.end()[-1] != '\0');
|
||||
|
||||
// The time zone identifier must be a null-terminated string.
|
||||
if (!timeZone.append('\0')) {
|
||||
return Err(ICUError::OutOfMemory);
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ucal_setDefaultTimeZone(timeZone.begin(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return Err(ToICUError(status));
|
||||
}
|
||||
|
||||
return Ok{};
|
||||
}
|
||||
#endif
|
||||
|
||||
Result<bool, ICUError> TimeZone::SetDefaultTimeZone(
|
||||
Span<const char> aTimeZone) {
|
||||
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
|
||||
icu::UnicodeString tzid(aTimeZone.data(), aTimeZone.size(), US_INV);
|
||||
if (tzid.isBogus()) {
|
||||
return Err(ICUError::OutOfMemory);
|
||||
}
|
||||
|
||||
UniquePtr<icu::TimeZone> newTimeZone(icu::TimeZone::createTimeZone(tzid));
|
||||
MOZ_ASSERT(newTimeZone);
|
||||
|
||||
if (*newTimeZone != icu::TimeZone::getUnknown()) {
|
||||
// adoptDefault() takes ownership of the time zone.
|
||||
icu::TimeZone::adoptDefault(newTimeZone.release());
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
TimeZoneIdentifierVector tzid;
|
||||
if (!tzid.append(aTimeZone.data(), aTimeZone.size())) {
|
||||
return Err(ICUError::OutOfMemory);
|
||||
}
|
||||
|
||||
// Retrieve the current default time zone in case we need to restore it.
|
||||
TimeZoneIdentifierVector defaultTimeZone;
|
||||
MOZ_TRY(FillVectorWithICUCall(defaultTimeZone, ucal_getDefaultTimeZone));
|
||||
|
||||
// Try to set the new time zone.
|
||||
MOZ_TRY(mozilla::intl::SetDefaultTimeZone(tzid));
|
||||
|
||||
// Check if the time zone was actually applied.
|
||||
TimeZoneIdentifierVector newTimeZone;
|
||||
MOZ_TRY(FillVectorWithICUCall(newTimeZone, ucal_getDefaultTimeZone));
|
||||
|
||||
// Return if the new time zone was successfully applied.
|
||||
if (!IsUnknownTimeZone(newTimeZone)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise restore the original time zone.
|
||||
MOZ_TRY(mozilla::intl::SetDefaultTimeZone(defaultTimeZone));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ICUResult TimeZone::SetDefaultTimeZoneFromHostTimeZone() {
|
||||
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
|
||||
if (icu::TimeZone* defaultZone = icu::TimeZone::detectHostTimeZone()) {
|
||||
icu::TimeZone::adoptDefault(defaultZone);
|
||||
}
|
||||
#else
|
||||
TimeZoneIdentifierVector hostTimeZone;
|
||||
MOZ_TRY(FillVectorWithICUCall(hostTimeZone, ucal_getHostTimeZone));
|
||||
|
||||
MOZ_TRY(mozilla::intl::SetDefaultTimeZone(hostTimeZone));
|
||||
#endif
|
||||
|
||||
return Ok{};
|
||||
}
|
||||
|
||||
Result<SpanEnumeration<char>, ICUError> TimeZone::GetAvailableTimeZones(
|
||||
const char* aRegion) {
|
||||
// Get the time zones that are commonly used in the given region. Uses the
|
||||
|
|
|
@ -143,6 +143,28 @@ class TimeZone final {
|
|||
return FillBufferWithICUCall(aBuffer, ucal_getDefaultTimeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default time zone.
|
||||
*/
|
||||
static Result<bool, ICUError> SetDefaultTimeZone(Span<const char> aTimeZone);
|
||||
|
||||
/**
|
||||
* Set the default time zone using the host system's time zone.
|
||||
*
|
||||
* NOTE: This function is not thread-safe.
|
||||
*/
|
||||
static ICUResult SetDefaultTimeZoneFromHostTimeZone();
|
||||
|
||||
/**
|
||||
* Constant for the typical maximal length of a time zone identifier.
|
||||
*
|
||||
* At the time of this writing 32 characters fits every supported time zone:
|
||||
*
|
||||
* Intl.supportedValuesOf("timeZone")
|
||||
* .reduce((acc, v) => Math.max(acc, v.length), 0)
|
||||
*/
|
||||
static constexpr size_t TimeZoneIdentifierLength = 32;
|
||||
|
||||
/**
|
||||
* Returns the canonical system time zone ID or the normalized custom time
|
||||
* zone ID for the given time zone ID.
|
||||
|
@ -157,11 +179,7 @@ class TimeZone final {
|
|||
// ucal_getCanonicalTimeZoneID differs from other API calls and fails when
|
||||
// passed a nullptr or 0 length result. Reserve some space initially so
|
||||
// that a real pointer will be used in the API.
|
||||
//
|
||||
// At the time of this writing 32 characters fits every time zone listed
|
||||
// in: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
// https://gist.github.com/gregtatum/f926de157a44e5965864da866fe71e63
|
||||
if (!aBuffer.reserve(32)) {
|
||||
if (!aBuffer.reserve(TimeZoneIdentifierLength)) {
|
||||
return Err(ICUError::OutOfMemory);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче