diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 8e8b5bf228f..39f4b41f988 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -2326,7 +2326,7 @@ static String convert_number_to_date_string(double input)
// date string that represents the date that, in UTC, is current input milliseconds after midnight UTC
// on the morning of 1970-01-01 (the time represented by the value "1970-01-01T00:00:00.0Z").
auto date = AK::UnixDateTime::from_seconds_since_epoch(input / 1000.);
- return MUST(date.to_string("%Y-%m-%d"sv));
+ return MUST(date.to_string("%Y-%m-%d"sv, AK::UnixDateTime::LocalTime::No));
}
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-number-string
diff --git a/Libraries/LibWeb/Internals/Internals.cpp b/Libraries/LibWeb/Internals/Internals.cpp
index b9c75e61d6a..8aa181d2e7c 100644
--- a/Libraries/LibWeb/Internals/Internals.cpp
+++ b/Libraries/LibWeb/Internals/Internals.cpp
@@ -4,7 +4,9 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include
#include
+#include
#include
#include
#include
@@ -53,6 +55,17 @@ void Internals::gc()
vm().heap().collect_garbage();
}
+WebIDL::ExceptionOr Internals::set_time_zone(StringView time_zone)
+{
+ auto current_time_zone = Unicode::current_time_zone();
+
+ 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();
+ return current_time_zone;
+}
+
JS::Object* Internals::hit_test(double x, double y)
{
auto& active_document = window().associated_document();
diff --git a/Libraries/LibWeb/Internals/Internals.h b/Libraries/LibWeb/Internals/Internals.h
index 070053d6162..806d0f23492 100644
--- a/Libraries/LibWeb/Internals/Internals.h
+++ b/Libraries/LibWeb/Internals/Internals.h
@@ -23,6 +23,8 @@ public:
void signal_test_is_done(String const& text);
void set_test_timeout(double milliseconds);
+ WebIDL::ExceptionOr set_time_zone(StringView time_zone);
+
void gc();
JS::Object* hit_test(double x, double y);
diff --git a/Libraries/LibWeb/Internals/Internals.idl b/Libraries/LibWeb/Internals/Internals.idl
index 27ad7e3c2fe..30e61fc6d16 100644
--- a/Libraries/LibWeb/Internals/Internals.idl
+++ b/Libraries/LibWeb/Internals/Internals.idl
@@ -8,6 +8,8 @@ interface Internals {
undefined signalTestIsDone(DOMString text);
undefined setTestTimeout(double milliseconds);
+ DOMString setTimeZone(DOMString timeZone);
+
undefined gc();
object hitTest(double x, double y);
diff --git a/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Libraries/LibWeb/Loader/ResourceLoader.cpp
index f4456fd58eb..9d3270d9153 100644
--- a/Libraries/LibWeb/Loader/ResourceLoader.cpp
+++ b/Libraries/LibWeb/Loader/ResourceLoader.cpp
@@ -146,7 +146,7 @@ static HTTP::HeaderMap response_headers_for_file(StringView path, Optional {
+ const originalTimeZone = internals.setTimeZone('America/New_York');
+
+ const input = document.createElement('input');
+ input.type = 'date';
+ input.valueAsDate = new Date(0);
+ const result = input.value;
+
+ internals.setTimeZone(originalTimeZone);
+ return result;
+ });
+
+ // 8. Input date set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'date';
@@ -68,7 +81,20 @@
return input.value;
});
- // 8. Input date invalid set value as date
+ // 9. Input date set value as date (non-UTC time zone)
+ testPart(() => {
+ const originalTimeZone = internals.setTimeZone('Europe/Paris');
+
+ const input = document.createElement('input');
+ input.type = "date";
+ input.valueAsDate = new Date(1702320457860);
+ const result = input.value;
+
+ internals.setTimeZone(originalTimeZone);
+ return result;
+ });
+
+ // 10. Input date invalid set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'date';
@@ -76,7 +102,7 @@
return input.value;
});
- // 9. Input date null set value as date
+ // 11. Input date null set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'date';
@@ -84,7 +110,7 @@
return input.value;
});
- // 10. Input time set value as date
+ // 12. Input time set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'time';
@@ -92,7 +118,7 @@
return input.value;
});
- // 11. Input time set value as date
+ // 13. Input time set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'time';
@@ -100,7 +126,7 @@
return input.value;
});
- // 12. Input time set value as date
+ // 14. Input time set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'time';
@@ -108,7 +134,7 @@
return input.value;
});
- // 13. Input time invalid set value as date
+ // 15. Input time invalid set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'time';
@@ -116,7 +142,7 @@
return input.value;
});
- // 14. Input time null set value as date
+ // 16. Input time null set value as date
testPart(() => {
const input = document.createElement('input');
input.type = 'time';