Bug 1709867 - Add a ICU-only DateTimeInfo::timeZoneId method. r=anba,platform-i18n-reviewers,dminor

Differential Revision: https://phabricator.services.mozilla.com/D169611
This commit is contained in:
Tom Schuster 2023-03-15 13:53:54 +00:00
Родитель 8ae10544b1
Коммит c46852b04b
5 изменённых файлов: 54 добавлений и 54 удалений

Просмотреть файл

@ -106,23 +106,7 @@ class TimeZone final {
mTimeZone->getDisplayName(static_cast<bool>(aDaylightSavings),
icu::TimeZone::LONG, icu::Locale(aLocale),
displayName);
int32_t length = displayName.length();
if (!aBuffer.reserve(AssertedCast<size_t>(length))) {
return Err(ICUError::OutOfMemory);
}
// Copy the display name.
UErrorCode status = U_ZERO_ERROR;
int32_t written = displayName.extract(aBuffer.data(), length, status);
if (!ICUSuccessForStringSpan(status)) {
return Err(ToICUError(status));
}
MOZ_ASSERT(written == length);
aBuffer.written(written);
return Ok{};
return FillBuffer(displayName, aBuffer);
#else
return FillBufferWithICUCall(
aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
@ -134,6 +118,23 @@ class TimeZone final {
#endif
}
/**
* Return the identifier for this time zone.
*/
template <typename B>
ICUResult GetId(B& aBuffer) {
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
icu::UnicodeString id;
mTimeZone->getID(id);
return FillBuffer(id, aBuffer);
#else
return FillBufferWithICUCall(
aBuffer, [&](UChar* target, int32_t length, UErrorCode* status) {
return ucal_getTimeZoneID(mCalendar, target, length, status);
});
#endif
}
/**
* Fill the buffer with the system's default IANA time zone identifier, e.g.
* "America/Chicago".
@ -225,6 +226,25 @@ class TimeZone final {
static Result<SpanEnumeration<char>, ICUError> GetAvailableTimeZones();
private:
template <typename B>
static ICUResult FillBuffer(const icu::UnicodeString& aString, B& aBuffer) {
int32_t length = aString.length();
if (!aBuffer.reserve(AssertedCast<size_t>(length))) {
return Err(ICUError::OutOfMemory);
}
UErrorCode status = U_ZERO_ERROR;
int32_t written = aString.extract(aBuffer.data(), length, status);
if (!ICUSuccessForStringSpan(status)) {
return Err(ToICUError(status));
}
MOZ_ASSERT(written == length);
aBuffer.written(written);
return Ok{};
}
#if MOZ_INTL_USE_ICU_CPP_TIMEZONE
UniquePtr<icu::TimeZone> mTimeZone = nullptr;
#else

Просмотреть файл

@ -107,6 +107,7 @@
#include "util/Text.h"
#include "vm/BooleanObject.h"
#include "vm/DateObject.h"
#include "vm/DateTime.h"
#include "vm/ErrorObject.h"
#include "vm/GlobalObject.h"
#include "vm/HelperThreads.h"
@ -7959,7 +7960,7 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) {
intl::FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> buf(cx);
if (auto ok = mozilla::intl::TimeZone::GetDefaultTimeZone(buf); ok.isErr()) {
if (auto ok = DateTimeInfo::timeZoneId(buf); ok.isErr()) {
intl::ReportInternalError(cx, ok.unwrapErr());
return false;
}

Просмотреть файл

@ -402,13 +402,8 @@ bool js::intl_defaultTimeZone(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
// The current default might be stale, because JS::ResetTimeZone() doesn't
// immediately update ICU's default time zone. So perform an update if
// needed.
js::ResyncICUDefaultTimeZone();
FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> timeZone(cx);
auto result = mozilla::intl::TimeZone::GetDefaultTimeZone(timeZone);
auto result = DateTimeInfo::timeZoneId(timeZone);
if (result.isErr()) {
intl::ReportInternalError(cx, result.unwrapErr());
return false;
@ -455,13 +450,8 @@ bool js::intl_isDefaultTimeZone(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
// The current default might be stale, because JS::ResetTimeZone() doesn't
// immediately update ICU's default time zone. So perform an update if
// needed.
js::ResyncICUDefaultTimeZone();
FormatBuffer<char16_t, intl::INITIAL_CHAR_BUFFER_SIZE> chars(cx);
auto result = mozilla::intl::TimeZone::GetDefaultTimeZone(chars);
auto result = DateTimeInfo::timeZoneId(chars);
if (result.isErr()) {
intl::ReportInternalError(cx, result.unwrapErr());
return false;

Просмотреть файл

@ -729,10 +729,6 @@ static bool ReadTimeZoneLink(std::string_view tz,
# endif /* defined(XP_WIN) */
#endif /* JS_HAS_INTL_API */
void js::ResyncICUDefaultTimeZone() {
js::DateTimeInfo::resyncICUDefaultTimeZone();
}
void js::DateTimeInfo::internalResyncICUDefaultTimeZone() {
#if JS_HAS_INTL_API
if (const char* tzenv = std::getenv("TZ")) {

Просмотреть файл

@ -15,9 +15,8 @@
#include "threading/ExclusiveData.h"
#if JS_HAS_INTL_API
namespace mozilla::intl {
class TimeZone;
}
# include "mozilla/intl/ICU4CGlue.h"
# include "mozilla/intl/TimeZone.h"
#endif
namespace js {
@ -62,15 +61,6 @@ enum class ResetTimeZoneMode : bool {
*/
extern void ResetTimeZoneInternal(ResetTimeZoneMode mode);
/**
* ICU's default time zone, used for various date/time formatting operations
* that include the local time in the representation, is allowed to go stale
* for unfortunate performance reasons. Call this function when an up-to-date
* default time zone is required, to resync ICU's default time zone with
* reality.
*/
extern void ResyncICUDefaultTimeZone();
/**
* Stores date/time information, particularly concerning the current local
* time zone, and implements a small cache for daylight saving time offset
@ -186,6 +176,16 @@ class DateTimeInfo {
return guard->internalTimeZoneDisplayName(buf, buflen, utcMilliseconds,
locale);
}
/**
* Copy the identifier for the current time zone to the provided resizable
* buffer.
*/
template <typename B>
static mozilla::intl::ICUResult timeZoneId(B& buffer) {
auto guard = acquireLockWithValidTimeZone();
return guard->timeZone()->GetId(buffer);
}
#else
/**
* Return the local time zone adjustment (ES2019 20.3.1.7) as computed by
@ -197,21 +197,14 @@ class DateTimeInfo {
#endif /* JS_HAS_INTL_API */
private:
// The two methods below should only be called via js::ResetTimeZoneInternal()
// and js::ResyncICUDefaultTimeZone().
// The method below should only be called via js::ResetTimeZoneInternal().
friend void js::ResetTimeZoneInternal(ResetTimeZoneMode);
friend void js::ResyncICUDefaultTimeZone();
static void resetTimeZone(ResetTimeZoneMode mode) {
auto guard = instance->lock();
guard->internalResetTimeZone(mode);
}
static void resyncICUDefaultTimeZone() {
auto guard = acquireLockWithValidTimeZone();
(void)guard;
}
struct RangeCache {
// Start and end offsets in seconds describing the current and the
// last cached range.