diff --git a/Libraries/LibUnicode/TimeZone.cpp b/Libraries/LibUnicode/TimeZone.cpp index d1bc1fff42a..acd43715c8d 100644 --- a/Libraries/LibUnicode/TimeZone.cpp +++ b/Libraries/LibUnicode/TimeZone.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -24,8 +24,8 @@ String current_time_zone() UErrorCode status = U_ZERO_ERROR; - auto time_zone = adopt_own_if_nonnull(icu::TimeZone::detectHostTimeZone()); - if (!time_zone) + auto time_zone = adopt_own_if_nonnull(icu::TimeZone::createDefault()); + if (!time_zone || *time_zone == icu::TimeZone::getUnknown()) return "UTC"_string; icu::UnicodeString time_zone_id; @@ -46,6 +46,18 @@ void clear_system_time_zone_cache() cached_system_time_zone.clear(); } +ErrorOr set_current_time_zone(StringView time_zone) +{ + auto time_zone_data = TimeZoneData::for_time_zone(time_zone); + if (!time_zone_data.has_value()) + return Error::from_string_literal("Unable to find the provided time zone"); + + icu::TimeZone::setDefault(time_zone_data->time_zone()); + clear_system_time_zone_cache(); + + return {}; +} + // https://github.com/unicode-org/icu/blob/main/icu4c/source/tools/tzcode/icuzones static constexpr bool is_legacy_non_iana_time_zone(StringView time_zone) { diff --git a/Libraries/LibUnicode/TimeZone.h b/Libraries/LibUnicode/TimeZone.h index 518589d1fd7..66f1601ff15 100644 --- a/Libraries/LibUnicode/TimeZone.h +++ b/Libraries/LibUnicode/TimeZone.h @@ -1,11 +1,12 @@ /* - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once +#include #include #include #include @@ -24,6 +25,7 @@ struct TimeZoneOffset { }; String current_time_zone(); +ErrorOr set_current_time_zone(StringView); void clear_system_time_zone_cache(); Vector const& available_time_zones(); Vector available_time_zones_in_region(StringView region); diff --git a/Tests/LibJS/test-js.cpp b/Tests/LibJS/test-js.cpp index 1ada18db2f8..eeeb2b88393 100644 --- a/Tests/LibJS/test-js.cpp +++ b/Tests/LibJS/test-js.cpp @@ -6,14 +6,11 @@ */ #include -#include #include #include #include #include #include -#include -#include TEST_ROOT("Libraries/LibJS/Tests"); @@ -111,23 +108,13 @@ TESTJS_GLOBAL_FUNCTION(detach_array_buffer, detachArrayBuffer) TESTJS_GLOBAL_FUNCTION(set_time_zone, setTimeZone) { - auto current_time_zone = JS::js_null(); + auto current_time_zone = JS::PrimitiveString::create(vm, Unicode::current_time_zone()); + auto time_zone = TRY(vm.argument(0).to_string(vm)); - if (auto time_zone = Core::Environment::get("TZ"sv); time_zone.has_value()) - current_time_zone = JS::PrimitiveString::create(vm, *time_zone); - - if (auto time_zone = vm.argument(0); time_zone.is_null()) { - if (auto result = Core::Environment::unset("TZ"sv); result.is_error()) - return vm.throw_completion(MUST(String::formatted("Could not unset time zone: {}", result.error()))); - } else { - if (auto result = Core::Environment::set("TZ"sv, TRY(time_zone.to_string(vm)), Core::Environment::Overwrite::Yes); result.is_error()) - return vm.throw_completion(MUST(String::formatted("Could not set time zone: {}", result.error()))); - } + if (auto result = Unicode::set_current_time_zone(time_zone); result.is_error()) + return vm.throw_completion(MUST(String::formatted("Could not set time zone: {}", result.error()))); JS::clear_system_time_zone_cache(); - Unicode::clear_system_time_zone_cache(); - tzset(); - return current_time_zone; } diff --git a/Tests/LibUnicode/TestTimeZone.cpp b/Tests/LibUnicode/TestTimeZone.cpp index 208a0b90137..c79a200124f 100644 --- a/Tests/LibUnicode/TestTimeZone.cpp +++ b/Tests/LibUnicode/TestTimeZone.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,29 +7,25 @@ #include #include -#include #include class TimeZoneGuard { public: explicit TimeZoneGuard(StringView time_zone) - : m_time_zone(Core::Environment::get("TZ"sv)) + : m_time_zone(Unicode::current_time_zone()) { - MUST(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes)); - Unicode::clear_system_time_zone_cache(); + (void)Unicode::set_current_time_zone(time_zone); } ~TimeZoneGuard() { - if (m_time_zone.has_value()) - MUST(Core::Environment::set("TZ"sv, *m_time_zone, Core::Environment::Overwrite::Yes)); - else - MUST(Core::Environment::unset("TZ"sv)); - Unicode::clear_system_time_zone_cache(); + MUST(Unicode::set_current_time_zone(m_time_zone)); } + String const& time_zone() const { return m_time_zone; } + private: - Optional m_time_zone; + String m_time_zone; }; TEST_CASE(current_time_zone) @@ -38,9 +34,13 @@ TEST_CASE(current_time_zone) TimeZoneGuard guard { "America/New_York"sv }; EXPECT_EQ(Unicode::current_time_zone(), "America/New_York"sv); } + { + TimeZoneGuard guard { "America/Los_Angeles"sv }; + EXPECT_EQ(Unicode::current_time_zone(), "America/Los_Angeles"sv); + } { TimeZoneGuard guard { "ladybird"sv }; - EXPECT_EQ(Unicode::current_time_zone(), "UTC"sv); + EXPECT_EQ(Unicode::current_time_zone(), guard.time_zone()); } }