diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index ac12a592431..8e02be0eb50 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -2308,6 +2308,29 @@ static String convert_number_to_time_string(double input)
return MUST(String::formatted("{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input)));
}
+// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):concept-input-value-number-string
+static String convert_number_to_local_date_and_time_string(double input)
+{
+ // The algorithm to convert a number to a string, given a number input, is as follows: Return a valid
+ // normalized local date and time string that represents the date and time that is input milliseconds
+ // after midnight on the morning of 1970-01-01 (the time represented by the value "1970-01-01T00:00:00.0").
+ auto year = JS::year_from_time(input);
+ auto month = JS::month_from_time(input) + 1; // Adjust for zero-based month
+ auto day = JS::date_from_time(input);
+ auto hour = JS::hour_from_time(input);
+ auto minutes = JS::min_from_time(input);
+ auto seconds = JS::sec_from_time(input);
+ auto milliseconds = JS::ms_from_time(input);
+
+ if (seconds > 0) {
+ if (milliseconds > 0)
+ return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:03d}", year, month, day, hour, minutes, seconds, milliseconds));
+ return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}", year, month, day, hour, minutes, seconds));
+ }
+
+ return MUST(String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}", year, month, day, hour, minutes));
+}
+
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-number
String HTMLInputElement::convert_number_to_string(double input) const
{
@@ -2331,6 +2354,9 @@ String HTMLInputElement::convert_number_to_string(double input) const
if (type_state() == TypeAttributeState::Time)
return convert_number_to_time_string(input);
+ if (type_state() == TypeAttributeState::LocalDateAndTime)
+ return convert_number_to_local_date_and_time_string(input);
+
dbgln("HTMLInputElement::convert_number_to_string() not implemented for input type {}", type());
return {};
}
diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt
index 34d9e60bbfb..edde99ed0dc 100644
--- a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt
+++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt
@@ -2,8 +2,8 @@ Harness status: OK
Found 60 tests
-54 Pass
-6 Fail
+56 Pass
+4 Fail
Pass valueAsNumber getter on type date (actual value: , expected valueAsNumber: NaN)
Pass valueAsNumber getter on type date (actual value: 0000-12-10, expected valueAsNumber: NaN)
Pass valueAsNumber getter on type date (actual value: 2019-00-12, expected valueAsNumber: NaN)
@@ -43,8 +43,8 @@ Pass valueAsNumber setter on type time (actual valueAsNumber: 86340000, expected
Pass valueAsNumber getter on type datetime-local (actual value: , expected valueAsNumber: NaN)
Fail valueAsNumber getter on type datetime-local (actual value: 2019-12-10T00:00, expected valueAsNumber: 1575936000000)
Fail valueAsNumber getter on type datetime-local (actual value: 2019-12-10T12:00, expected valueAsNumber: 1575979200000)
-Fail valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575936000000, expected value: 2019-12-10T00:00)
-Fail valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575979200000, expected value: 2019-12-10T12:00)
+Pass valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575936000000, expected value: 2019-12-10T00:00)
+Pass valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575979200000, expected value: 2019-12-10T12:00)
Pass valueAsNumber getter on type number (actual value: , expected valueAsNumber: NaN)
Pass valueAsNumber getter on type number (actual value: 123, expected valueAsNumber: 123)
Pass valueAsNumber getter on type number (actual value: 123.456, expected valueAsNumber: 123.456)