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 + + + + +

+

input_valueAsDate_stepping

+ +

+ +
+ +
+ +
+

+

+

+

+
+ + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.html b/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.html new file mode 100644 index 00000000000..61835d7eaec --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/semantics/forms/the-input-element/input-valueasdate.html @@ -0,0 +1,108 @@ + + + + + HTMLInputElement valueAsDate + + + + + + + +

input_valueAsDate

+
+
+ + + + + + + + +