LibUnicode: Add a cache for ICU calendar objects
Analogous to our existing locale and time zone caches.
This commit is contained in:
parent
a41f2f56a8
commit
b6699d439a
3 changed files with 65 additions and 10 deletions
|
|
@ -627,16 +627,7 @@ static void apply_time_zone_to_formatter(icu::SimpleDateFormat& formatter, icu::
|
|||
auto* calendar = icu::Calendar::createInstance(time_zone_data->time_zone(), locale, status);
|
||||
verify_icu_success(status);
|
||||
|
||||
if (calendar->getDynamicClassID() == icu::GregorianCalendar::getStaticClassID()) {
|
||||
// https://tc39.es/ecma262/#sec-time-values-and-time-range
|
||||
// A time value supports a slightly smaller range of -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds.
|
||||
static constexpr double ECMA_262_MINIMUM_TIME = -8.64E15;
|
||||
|
||||
auto* gregorian_calendar = static_cast<icu::GregorianCalendar*>(calendar);
|
||||
gregorian_calendar->setGregorianChange(ECMA_262_MINIMUM_TIME, status);
|
||||
verify_icu_success(status);
|
||||
}
|
||||
|
||||
CalendarData::adjust_time_range_for_proleptic_calendar(*calendar);
|
||||
formatter.adoptCalendar(calendar);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibUnicode/ICU.h>
|
||||
|
||||
#include <unicode/dtptngen.h>
|
||||
#include <unicode/gregocal.h>
|
||||
#include <unicode/locdspnm.h>
|
||||
#include <unicode/numsys.h>
|
||||
#include <unicode/tznames.h>
|
||||
|
|
@ -17,6 +18,7 @@
|
|||
namespace Unicode {
|
||||
|
||||
static HashMap<String, OwnPtr<LocaleData>> s_locale_cache;
|
||||
static HashMap<String, OwnPtr<CalendarData>> s_calendar_cache;
|
||||
static HashMap<String, OwnPtr<TimeZoneData>> s_time_zone_cache;
|
||||
|
||||
Optional<LocaleData&> LocaleData::for_locale(StringView locale)
|
||||
|
|
@ -114,6 +116,53 @@ icu::TimeZoneNames& LocaleData::time_zone_names()
|
|||
return *m_time_zone_names;
|
||||
}
|
||||
|
||||
Optional<CalendarData&> CalendarData::for_calendar(String const& calendar)
|
||||
{
|
||||
auto& calendar_data = s_calendar_cache.ensure(calendar, [&]() -> OwnPtr<CalendarData> {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
auto const* legacy_calendar = uloc_toLegacyType("calendar", ByteString(calendar).characters());
|
||||
if (!legacy_calendar)
|
||||
return nullptr;
|
||||
|
||||
auto locale_data = LocaleData::for_locale("und"sv);
|
||||
VERIFY(locale_data.has_value());
|
||||
|
||||
locale_data->locale().setKeywordValue("calendar", legacy_calendar, status);
|
||||
if (icu_failure(status))
|
||||
return nullptr;
|
||||
|
||||
auto icu_calendar = adopt_own_if_nonnull(icu::Calendar::createInstance(locale_data->locale(), status));
|
||||
if (icu_failure(status))
|
||||
return nullptr;
|
||||
|
||||
return adopt_own(*new CalendarData { icu_calendar.release_nonnull() });
|
||||
});
|
||||
|
||||
if (calendar_data)
|
||||
return *calendar_data;
|
||||
return {};
|
||||
}
|
||||
|
||||
void CalendarData::adjust_time_range_for_proleptic_calendar(icu::Calendar& icu_calendar)
|
||||
{
|
||||
// https://tc39.es/ecma262/#sec-time-values-and-time-range
|
||||
// A time value supports a slightly smaller range of -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds.
|
||||
static constexpr UDate ECMA_262_MINIMUM_TIME = -8.64E15;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
if (auto* gregorian_calendar = as_if<icu::GregorianCalendar>(icu_calendar)) {
|
||||
gregorian_calendar->setGregorianChange(ECMA_262_MINIMUM_TIME, status);
|
||||
verify_icu_success(status);
|
||||
}
|
||||
}
|
||||
|
||||
CalendarData::CalendarData(NonnullOwnPtr<icu::Calendar> calendar)
|
||||
: m_calendar(move(calendar))
|
||||
{
|
||||
adjust_time_range_for_proleptic_calendar(*m_calendar);
|
||||
}
|
||||
|
||||
Optional<TimeZoneData&> TimeZoneData::for_time_zone(StringView time_zone)
|
||||
{
|
||||
auto time_zone_data = s_time_zone_cache.get(time_zone);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <unicode/uversion.h>
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
class Calendar;
|
||||
class DateTimePatternGenerator;
|
||||
class LocaleDisplayNames;
|
||||
class NumberingSystem;
|
||||
|
|
@ -68,6 +69,20 @@ private:
|
|||
Optional<DigitalFormat> m_digital_format;
|
||||
};
|
||||
|
||||
class CalendarData {
|
||||
public:
|
||||
static Optional<CalendarData&> for_calendar(String const& calendar);
|
||||
|
||||
static void adjust_time_range_for_proleptic_calendar(icu::Calendar&);
|
||||
|
||||
ALWAYS_INLINE icu::Calendar& calendar() { return *m_calendar; }
|
||||
|
||||
private:
|
||||
explicit CalendarData(NonnullOwnPtr<icu::Calendar>);
|
||||
|
||||
NonnullOwnPtr<icu::Calendar> m_calendar;
|
||||
};
|
||||
|
||||
class TimeZoneData {
|
||||
public:
|
||||
static Optional<TimeZoneData&> for_time_zone(StringView time_zone);
|
||||
|
|
|
|||
Loading…
Reference in a new issue