LibUnicode: Cache all created icu::TimeZone objects

This cache works exactly the same as the existing icu::Locale cache.
This commit is contained in:
Timothy Flynn 2024-09-03 11:20:20 -04:00 committed by Andreas Kling
commit d392c38a73
Notes: github-actions[bot] 2024-09-03 17:26:56 +00:00
5 changed files with 45 additions and 7 deletions

View file

@ -622,9 +622,9 @@ static void apply_time_zone_to_formatter(icu::SimpleDateFormat& formatter, icu::
{
UErrorCode status = U_ZERO_ERROR;
auto* time_zone = icu::TimeZone::createTimeZone(icu_string(time_zone_identifier));
auto time_zone_data = TimeZoneData::for_time_zone(time_zone_identifier);
auto* calendar = icu::Calendar::createInstance(time_zone, locale, status);
auto* calendar = icu::Calendar::createInstance(time_zone_data->time_zone(), locale, status);
VERIFY(icu_success(status));
if (calendar->getDynamicClassID() == icu::GregorianCalendar::getStaticClassID()) {

View file

@ -17,6 +17,7 @@
namespace Unicode {
static HashMap<String, OwnPtr<LocaleData>> s_locale_cache;
static HashMap<String, OwnPtr<TimeZoneData>> s_time_zone_cache;
Optional<LocaleData&> LocaleData::for_locale(StringView locale)
{
@ -113,6 +114,30 @@ icu::TimeZoneNames& LocaleData::time_zone_names()
return *m_time_zone_names;
}
Optional<TimeZoneData&> TimeZoneData::for_time_zone(StringView time_zone)
{
auto time_zone_data = s_time_zone_cache.get(time_zone);
if (!time_zone_data.has_value()) {
time_zone_data = s_time_zone_cache.ensure(MUST(String::from_utf8(time_zone)), [&]() -> OwnPtr<TimeZoneData> {
auto icu_time_zone = adopt_own_if_nonnull(icu::TimeZone::createTimeZone(icu_string(time_zone)));
if (!icu_time_zone || *icu_time_zone == icu::TimeZone::getUnknown())
return nullptr;
return adopt_own(*new TimeZoneData { icu_time_zone.release_nonnull() });
});
}
if (time_zone_data.value())
return *time_zone_data.value();
return {};
}
TimeZoneData::TimeZoneData(NonnullOwnPtr<icu::TimeZone> time_zone)
: m_time_zone(move(time_zone))
{
}
Vector<icu::UnicodeString> icu_string_list(ReadonlySpan<String> strings)
{
Vector<icu::UnicodeString> result;

View file

@ -24,6 +24,7 @@ U_NAMESPACE_BEGIN
class DateTimePatternGenerator;
class LocaleDisplayNames;
class NumberingSystem;
class TimeZone;
class TimeZoneNames;
U_NAMESPACE_END
@ -63,6 +64,18 @@ private:
Optional<DigitalFormat> m_digital_format;
};
class TimeZoneData {
public:
static Optional<TimeZoneData&> for_time_zone(StringView time_zone);
ALWAYS_INLINE icu::TimeZone& time_zone() { return *m_time_zone; }
private:
explicit TimeZoneData(NonnullOwnPtr<icu::TimeZone>);
NonnullOwnPtr<icu::TimeZone> m_time_zone;
};
constexpr bool icu_success(UErrorCode code)
{
return static_cast<bool>(U_SUCCESS(code));

View file

@ -131,14 +131,14 @@ Optional<TimeZoneOffset> time_zone_offset(StringView time_zone, UnixDateTime tim
{
UErrorCode status = U_ZERO_ERROR;
auto icu_time_zone = adopt_own_if_nonnull(icu::TimeZone::createTimeZone(icu_string(time_zone)));
if (!icu_time_zone || *icu_time_zone == icu::TimeZone::getUnknown())
auto time_zone_data = TimeZoneData::for_time_zone(time_zone);
if (!time_zone_data.has_value())
return {};
i32 raw_offset = 0;
i32 dst_offset = 0;
icu_time_zone->getOffset(static_cast<UDate>(time.milliseconds_since_epoch()), 0, raw_offset, dst_offset, status);
time_zone_data->time_zone().getOffset(static_cast<UDate>(time.milliseconds_since_epoch()), 0, raw_offset, dst_offset, status);
if (icu_failure(status))
return {};

View file

@ -4,13 +4,13 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Time.h>
#include <AK/Vector.h>
#pragma once
namespace Unicode {
struct TimeZoneOffset {