LibUnicode: Cache the system time zone

It's expensive to determine the system time zone from disk each time it
is requested. This makes LibUnicode cache the result, and provides an
API to clear that cache. This will let us set up a monitor to watch for
system time zone changes in platform-dependent ways.
This commit is contained in:
Timothy Flynn 2024-08-24 12:07:24 -04:00 committed by Andreas Kling
parent e25681203e
commit b31c11bca5
Notes: github-actions[bot] 2024-08-25 07:48:47 +00:00
5 changed files with 27 additions and 3 deletions

View file

@ -10,6 +10,7 @@
#include <LibCore/DateTime.h> #include <LibCore/DateTime.h>
#include <LibCore/Environment.h> #include <LibCore/Environment.h>
#include <LibTest/TestCase.h> #include <LibTest/TestCase.h>
#include <LibUnicode/TimeZone.h>
#include <time.h> #include <time.h>
class TimeZoneGuard { class TimeZoneGuard {
@ -29,12 +30,14 @@ public:
else else
TRY_OR_FAIL(Core::Environment::unset("TZ"sv)); TRY_OR_FAIL(Core::Environment::unset("TZ"sv));
Unicode::clear_system_time_zone_cache();
tzset(); tzset();
} }
void update(StringView time_zone) void update(StringView time_zone)
{ {
TRY_OR_FAIL(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes)); TRY_OR_FAIL(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes));
Unicode::clear_system_time_zone_cache();
tzset(); tzset();
} }

View file

@ -8,6 +8,7 @@
#include <LibCore/Environment.h> #include <LibCore/Environment.h>
#include <LibJS/Runtime/ArrayBuffer.h> #include <LibJS/Runtime/ArrayBuffer.h>
#include <LibTest/JavaScriptTestRunner.h> #include <LibTest/JavaScriptTestRunner.h>
#include <LibUnicode/TimeZone.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
@ -106,6 +107,7 @@ TESTJS_GLOBAL_FUNCTION(set_time_zone, setTimeZone)
return vm.throw_completion<JS::InternalError>(MUST(String::formatted("Could not set time zone: {}", result.error()))); return vm.throw_completion<JS::InternalError>(MUST(String::formatted("Could not set time zone: {}", result.error())));
} }
Unicode::clear_system_time_zone_cache();
tzset(); tzset();
return current_time_zone; return current_time_zone;

View file

@ -16,6 +16,7 @@ public:
: m_time_zone(Core::Environment::get("TZ"sv)) : m_time_zone(Core::Environment::get("TZ"sv))
{ {
MUST(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes)); MUST(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes));
Unicode::clear_system_time_zone_cache();
} }
~TimeZoneGuard() ~TimeZoneGuard()
@ -24,6 +25,7 @@ public:
MUST(Core::Environment::set("TZ"sv, *m_time_zone, Core::Environment::Overwrite::Yes)); MUST(Core::Environment::set("TZ"sv, *m_time_zone, Core::Environment::Overwrite::Yes));
else else
MUST(Core::Environment::unset("TZ"sv)); MUST(Core::Environment::unset("TZ"sv));
Unicode::clear_system_time_zone_cache();
} }
private: private:

View file

@ -15,8 +15,13 @@
namespace Unicode { namespace Unicode {
String current_time_zone() static Optional<String> cached_system_time_zone;
String current_time_zone(UseTimeZoneCache)
{ {
if (cached_system_time_zone.has_value())
return *cached_system_time_zone;
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
auto time_zone = adopt_own_if_nonnull(icu::TimeZone::detectHostTimeZone()); auto time_zone = adopt_own_if_nonnull(icu::TimeZone::detectHostTimeZone());
@ -32,7 +37,13 @@ String current_time_zone()
if (icu_failure(status)) if (icu_failure(status))
return "UTC"_string; return "UTC"_string;
return icu_string_to_string(time_zone_name); cached_system_time_zone = icu_string_to_string(time_zone_name);
return *cached_system_time_zone;
}
void clear_system_time_zone_cache()
{
cached_system_time_zone.clear();
} }
// https://github.com/unicode-org/icu/blob/main/icu4c/source/tools/tzcode/icuzones // https://github.com/unicode-org/icu/blob/main/icu4c/source/tools/tzcode/icuzones

View file

@ -23,7 +23,13 @@ struct TimeZoneOffset {
InDST in_dst { InDST::No }; InDST in_dst { InDST::No };
}; };
String current_time_zone(); enum class UseTimeZoneCache {
No,
Yes,
};
String current_time_zone(UseTimeZoneCache = UseTimeZoneCache::Yes);
void clear_system_time_zone_cache();
Vector<String> const& available_time_zones(); Vector<String> const& available_time_zones();
Vector<String> available_time_zones_in_region(StringView region); Vector<String> available_time_zones_in_region(StringView region);
Optional<String> resolve_primary_time_zone(StringView time_zone); Optional<String> resolve_primary_time_zone(StringView time_zone);