From bd34b11ca29a80f33a143b2478b20b0a913dde99 Mon Sep 17 00:00:00 2001
From: Glenn Skrzypczak
Date: Tue, 26 Aug 2025 22:03:46 +0200
Subject: [PATCH] LibWeb/HTML: Implement date conversions for month and week
inputs
This implements the conversion algorithms between strings and dates for
inputs of the types month and week.
---
Libraries/LibWeb/HTML/HTMLInputElement.cpp | 48 ++++++++
.../input-valueasdate-stepping.txt | 9 ++
.../the-input-element/input-valueasdate.txt | 35 ++++++
.../input-valueasdate-stepping.html | 83 ++++++++++++++
.../the-input-element/input-valueasdate.html | 108 ++++++++++++++++++
5 files changed, 283 insertions(+)
create mode 100644 Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.txt
create mode 100644 Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.txt
create mode 100644 Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.html
create mode 100644 Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.html
diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 9f41af7aab5..e152d2bcd56 100644
--- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -2374,6 +2374,15 @@ static Utf16String convert_number_to_month_string(double input)
return Utf16String::formatted("{:04d}-{:02d}", static_cast(year), static_cast(months) + 1);
}
+// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):concept-input-value-date-string
+static Utf16String convert_date_to_month_string(double input)
+{
+ // The algorithm to convert a number to a string, given a number input, is as follows: Return a valid month
+ // string that represents the month that has input months between it and January 1970.
+ auto date = AK::UnixDateTime::from_milliseconds_since_epoch(input);
+ return date.to_utf16_string("%Y-%m"sv, AK::UnixDateTime::LocalTime::No);
+}
+
// https://html.spec.whatwg.org/multipage/input.html#concept-input-value-number-string
static Utf16String convert_number_to_week_string(double input)
{
@@ -2488,6 +2497,31 @@ WebIDL::ExceptionOr> HTMLInputElement::convert_string_to_date(
return JS::Date::create(realm(), JS::make_date(JS::make_day(date.year, date.month - 1, date.day), 0));
}
+ // https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):concept-input-value-string-date
+ if (type_state() == TypeAttributeState::Month) {
+ // If parsing a month from input results in an error, then return an error;
+ auto maybe_year_and_month = parse_a_month_string(input);
+ if (!maybe_year_and_month.has_value())
+ return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Can't parse month string"sv };
+ auto year_and_month = maybe_year_and_month.value();
+
+ // otherwise, return a new Date object representing midnight UTC on the morning of the first day of the parsed month.
+ return JS::Date::create(realm(), JS::make_date(JS::make_day(year_and_month.year, year_and_month.month - 1, 1), 0));
+ }
+
+ // https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):concept-input-value-string-date
+ if (type_state() == TypeAttributeState::Week) {
+ // If parsing a week from input results in an error, then return an error;
+ auto maybe_week = parse_a_week_string(input);
+ if (!maybe_week.has_value())
+ return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Can't parse week string"sv };
+ auto week = maybe_week.value();
+
+ // otherwise, return a new Date object representing midnight UTC on the morning of the Monday of the parsed week.
+ auto datetime = UnixDateTime::from_iso8601_week(week.week_year, week.week);
+ return JS::Date::create(realm(), datetime.milliseconds_since_epoch());
+ }
+
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-string-date
if (type_state() == TypeAttributeState::Time) {
// If parsing a time from input results in an error, then return an error;
@@ -2522,6 +2556,20 @@ Utf16String HTMLInputElement::convert_date_to_string(GC::Ref input) co
return convert_number_to_date_string(input->date_value());
}
+ // https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):concept-input-value-date-string
+ if (type_state() == TypeAttributeState::Month) {
+ // Return a valid month string that represents the month current at the time represented by input in the UTC time zone.
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
+ return convert_date_to_month_string(input->date_value());
+ }
+
+ // https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):concept-input-value-date-string
+ if (type_state() == TypeAttributeState::Week) {
+ // Return a valid week string that represents the week current at the time represented by input in the UTC time zone.
+ // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-week-string
+ return convert_number_to_week_string(input->date_value());
+ }
+
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-string-date
if (type_state() == TypeAttributeState::Time) {
// Return a valid time string that represents the UTC time component that is represented by input.
diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.txt
new file mode 100644
index 00000000000..46875000b5f
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.txt
@@ -0,0 +1,9 @@
+Harness status: OK
+
+Found 4 tests
+
+4 Pass
+Pass date should step correctly
+Pass time should step correctly
+Pass month should step correctly
+Pass week should step correctly
\ No newline at end of file
diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.txt
new file mode 100644
index 00000000000..e56bc58f6d8
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.txt
@@ -0,0 +1,35 @@
+Harness status: OK
+
+Found 30 tests
+
+30 Pass
+Pass valueAsDate getter on type date (with value: "")
+Pass valueAsDate getter on type date (with value: "0000-12-10")
+Pass valueAsDate getter on type date (with value: "2019-00-12")
+Pass valueAsDate getter on type date (with value: "2019-12-00")
+Pass valueAsDate getter on type date (with value: "2019-13-10")
+Pass valueAsDate getter on type date (with value: "2019-02-29")
+Pass valueAsDate getter on type date (with value: "2019-12-10")
+Pass valueAsDate getter on type date (with value: "2016-02-29")
+Pass valueAsDate setter on type date (new Date("2019-12-10T00:00:00.000Z"))
+Pass valueAsDate setter on type date (new Date("2016-02-29T00:00:00.000Z"))
+Pass valueAsDate getter on type month (with value: "")
+Pass valueAsDate getter on type month (with value: "0000-12")
+Pass valueAsDate getter on type month (with value: "2019-00")
+Pass valueAsDate getter on type month (with value: "2019-12")
+Pass valueAsDate setter on type month (new Date("2019-12-01T00:00:00.000Z"))
+Pass valueAsDate getter on type week (with value: "")
+Pass valueAsDate getter on type week (with value: "0000-W50")
+Pass valueAsDate getter on type week (with value: "2019-W00")
+Pass valueAsDate getter on type week (with value: "2019-W60")
+Pass valueAsDate getter on type week (with value: "2019-W50")
+Pass valueAsDate setter on type week (new Date("2019-12-09T00:00:00.000Z"))
+Pass valueAsDate getter on type time (with value: "")
+Pass valueAsDate getter on type time (with value: "24:00")
+Pass valueAsDate getter on type time (with value: "00:60")
+Pass valueAsDate getter on type time (with value: "00:00")
+Pass valueAsDate getter on type time (with value: "12:00")
+Pass valueAsDate getter on type time (with value: "23:59")
+Pass valueAsDate setter on type time (new Date("1970-01-01T00:00:00.000Z"))
+Pass valueAsDate setter on type time (new Date("1970-01-01T12:00:00.000Z"))
+Pass valueAsDate setter on type time (new Date("1970-01-01T23:59:00.000Z"))
\ No newline at end of file
diff --git a/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.html b/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.html
new file mode 100644
index 00000000000..f19730d511c
--- /dev/null
+++ b/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate-stepping.html
@@ -0,0 +1,83 @@
+
+
+
+ valueAsDate stepping
+
+
+
+
+