LibCore: Keep ICU and libc time zones in sync
Add Core::TimeZone as the single entry point for changing the current time zone. This updates both ICU and the process TZ/tzset state so libc-backed helpers such as AK::UnixDateTime::to_string() agree with JS/ICU time zone state. Previously only the ICU timezone would be updated, which could result in inconsistent results being returned.
This commit is contained in:
parent
8a85146e35
commit
74b76e21b9
9 changed files with 78 additions and 7 deletions
|
|
@ -25,6 +25,7 @@ set(SOURCES
|
|||
SystemServerTakeover.cpp
|
||||
ThreadEventQueue.cpp
|
||||
Timer.cpp
|
||||
TimeZone.cpp
|
||||
Version.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
27
Libraries/LibCore/TimeZone.cpp
Normal file
27
Libraries/LibCore/TimeZone.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibCore/Environment.h>
|
||||
#include <LibCore/TimeZone.h>
|
||||
#include <LibUnicode/TimeZone.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace Core::TimeZone {
|
||||
|
||||
ErrorOr<void> set_current_time_zone(StringView time_zone)
|
||||
{
|
||||
TRY(Unicode::set_current_time_zone(time_zone));
|
||||
TRY(Core::Environment::set("TZ"sv, time_zone, Core::Environment::Overwrite::Yes));
|
||||
tzset();
|
||||
return {};
|
||||
}
|
||||
|
||||
String current_time_zone()
|
||||
{
|
||||
return Unicode::current_time_zone();
|
||||
}
|
||||
|
||||
}
|
||||
20
Libraries/LibCore/TimeZone.h
Normal file
20
Libraries/LibCore/TimeZone.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibCore/Export.h>
|
||||
|
||||
namespace Core::TimeZone {
|
||||
|
||||
CORE_API ErrorOr<void> set_current_time_zone(StringView);
|
||||
|
||||
CORE_API String current_time_zone();
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/JsonObject.h>
|
||||
#include <LibCore/TimeZone.h>
|
||||
#include <LibGfx/Cursor.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Date.h>
|
||||
|
|
@ -13,7 +14,6 @@
|
|||
#include <LibJS/Runtime/Reference.h>
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibURL/Parser.h>
|
||||
#include <LibUnicode/TimeZone.h>
|
||||
#include <LibWeb/ARIA/AriaData.h>
|
||||
#include <LibWeb/ARIA/StateAndProperties.h>
|
||||
#include <LibWeb/Bindings/Internals.h>
|
||||
|
|
@ -207,9 +207,9 @@ WebIDL::ExceptionOr<void> Internals::mark_as_garbage(StringView variable_name)
|
|||
|
||||
WebIDL::ExceptionOr<String> Internals::set_time_zone(StringView time_zone)
|
||||
{
|
||||
auto current_time_zone = Unicode::current_time_zone();
|
||||
auto current_time_zone = Core::TimeZone::current_time_zone();
|
||||
|
||||
if (auto result = Unicode::set_current_time_zone(time_zone); result.is_error())
|
||||
if (auto result = Core::TimeZone::set_current_time_zone(time_zone); result.is_error())
|
||||
return vm().throw_completion<JS::InternalError>(MUST(String::formatted("Could not set time zone: {}", result.error())));
|
||||
|
||||
JS::clear_system_time_zone_cache();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <LibCore/Process.h>
|
||||
#include <LibCore/Resource.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibCore/TimeZone.h>
|
||||
#include <LibCrypto/OpenSSLForward.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/PathFontProvider.h>
|
||||
|
|
@ -183,7 +184,7 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
|
|||
}
|
||||
|
||||
if (!default_time_zone.is_empty()) {
|
||||
if (auto result = Unicode::set_current_time_zone(default_time_zone); result.is_error())
|
||||
if (auto result = Core::TimeZone::set_current_time_zone(default_time_zone); result.is_error())
|
||||
dbgln("Failed to set default time zone: {}", result.error());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
#include <AK/Enumerate.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibCore/TimeZone.h>
|
||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||
#include <LibJS/Runtime/Date.h>
|
||||
#include <LibJS/Runtime/FinalizationRegistry.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
#include <LibJS/Runtime/ValueInlines.h>
|
||||
#include <LibTest/JavaScriptTestRunner.h>
|
||||
#include <LibUnicode/TimeZone.h>
|
||||
|
||||
TEST_ROOT("Tests/LibJS/Runtime");
|
||||
|
||||
|
|
@ -142,10 +142,10 @@ TESTJS_GLOBAL_FUNCTION(detach_array_buffer, detachArrayBuffer)
|
|||
|
||||
TESTJS_GLOBAL_FUNCTION(set_time_zone, setTimeZone)
|
||||
{
|
||||
auto current_time_zone = JS::PrimitiveString::create(vm, Unicode::current_time_zone());
|
||||
auto current_time_zone = JS::PrimitiveString::create(vm, Core::TimeZone::current_time_zone());
|
||||
auto time_zone = TRY(vm.argument(0).to_string(vm));
|
||||
|
||||
if (auto result = Unicode::set_current_time_zone(time_zone); result.is_error())
|
||||
if (auto result = Core::TimeZone::set_current_time_zone(time_zone); result.is_error())
|
||||
return vm.throw_completion<JS::InternalError>(MUST(String::formatted("Could not set time zone: {}", result.error())));
|
||||
|
||||
JS::clear_system_time_zone_cache();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass lastModified should return the last modified date and time
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>document.lastModified</title>
|
||||
<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
|
||||
<link rel=help href="https://html.spec.whatwg.org/multipage/#resource-metadata-management">
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function(){
|
||||
var date = new Date("Thu, 01 Jan 1970 01:23:45 GMT");
|
||||
var result = ('0' + (date.getMonth()+1)).slice(-2) + '/' + ('0' + date.getDate()).slice(-2) + '/' + date.getFullYear() + " " + [date.getHours(),date.getMinutes(),date.getSeconds()].map(function(n){return ("0" + n).slice(-2);}).join(":");
|
||||
assert_equals(document.lastModified, result);
|
||||
}, "lastModified should return the last modified date and time");
|
||||
</script>
|
||||
|
|
@ -0,0 +1 @@
|
|||
Last-Modified: Thu, 01 Jan 1970 01:23:45 GMT
|
||||
Loading…
Reference in a new issue