소스 검색

LibJS: Parse date strings like "9/17/2022"

davidot 2 년 전
부모
커밋
03c468fb7d
2개의 변경된 파일29개의 추가작업 그리고 3개의 파일을 삭제
  1. 14 3
      Userland/Libraries/LibJS/Runtime/DateConstructor.cpp
  2. 15 0
      Userland/Libraries/LibJS/Tests/builtins/Date/Date.parse.js

+ 14 - 3
Userland/Libraries/LibJS/Runtime/DateConstructor.cpp

@@ -147,6 +147,11 @@ static double parse_simplified_iso8601(String const& iso_8601)
     return time_clip(time_ms);
 }
 
+static constexpr AK::Array<StringView, 2> extra_formats = {
+    "%a %b %e %T %z %Y"sv,
+    "%m/%e/%Y"sv
+};
+
 static double parse_date_string(String const& date_string)
 {
     auto value = parse_simplified_iso8601(date_string);
@@ -155,9 +160,15 @@ static double parse_date_string(String const& date_string)
 
     // Date.parse() is allowed to accept an arbitrary number of implementation-defined formats.
     // Parse formats of this type: "Wed Apr 17 23:08:53 +0000 2019"
-    auto maybe_datetime = Core::DateTime::parse("%a %b %e %T %z %Y"sv, date_string);
-    if (maybe_datetime.has_value())
-        return 1000.0 * maybe_datetime->timestamp();
+    // And: "4/17/2019"
+    // FIXME: Exactly what timezone and which additional formats we should support is unclear.
+    //        Both Chrome and Firefox seem to support "4/17/2019 11:08 PM +0000" with most parts
+    //        being optional, however this is not clearly documented anywhere.
+    for (auto const& format : extra_formats) {
+        auto maybe_datetime = Core::DateTime::parse(format, date_string);
+        if (maybe_datetime.has_value())
+            return 1000.0 * maybe_datetime->timestamp();
+    }
 
     return NAN;
 }

+ 15 - 0
Userland/Libraries/LibJS/Tests/builtins/Date/Date.parse.js

@@ -63,3 +63,18 @@ test("extra micro seconds extension", () => {
     expect(Date.parse("2021-06-26T07:24:40.0079999999999999999+00:00")).toBe(1624692280007);
     expect(Date.parse("2021-04-15T18:47:25.606000+00:00")).toBe(1618512445606);
 });
+
+test("extra date extension", () => {
+    function expectStringToGiveDate(input, fullYear, month, dayInMonth) {
+        // Since the timezone is not specified we just say it has to equal the date parts.
+        const date = new Date(Date.parse(input));
+        expect(date.getFullYear()).toBe(fullYear);
+        expect(date.getMonth() + 1).toBe(month);
+        expect(date.getDate()).toBe(dayInMonth);
+    }
+
+    expectStringToGiveDate("01/30/2021", 2021, 1, 30);
+    expectStringToGiveDate("10/1/2021", 2021, 10, 1);
+    expectStringToGiveDate("7/07/1977", 1977, 7, 7);
+    expectStringToGiveDate("2/27/3058", 3058, 2, 27);
+});