Prechádzať zdrojové kódy

LibJS: Implement Date.prototype.toISOString()

Nico Weber 4 rokov pred
rodič
commit
a6b68451dc

+ 33 - 0
Libraries/LibJS/Runtime/Date.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
 
 
+#include <AK/StringBuilder.h>
 #include <LibCore/DateTime.h>
 #include <LibCore/DateTime.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Interpreter.h>
@@ -48,4 +49,36 @@ Date::~Date()
 {
 {
 }
 }
 
 
+String Date::iso_date_string() const
+{
+    time_t timestamp = m_datetime.timestamp();
+    struct tm tm;
+    gmtime_r(&timestamp, &tm);
+    int year = tm.tm_year + 1900;
+    int month = tm.tm_mon + 1;
+
+    StringBuilder builder;
+    if (year < 0)
+        builder.appendf("-%06d", -year);
+    else if (year > 9999)
+        builder.appendf("+%06d", year);
+    else
+        builder.appendf("%04d", year);
+    builder.append('-');
+    builder.appendf("%02d", month);
+    builder.append('-');
+    builder.appendf("%02d", tm.tm_mday);
+    builder.append('T');
+    builder.appendf("%02d", tm.tm_hour);
+    builder.append(':');
+    builder.appendf("%02d", tm.tm_min);
+    builder.append(':');
+    builder.appendf("%02d", tm.tm_sec);
+    builder.append('.');
+    builder.appendf("%03d", m_milliseconds);
+    builder.append('Z');
+
+    return builder.build();
+}
+
 }
 }

+ 2 - 0
Libraries/LibJS/Runtime/Date.h

@@ -52,6 +52,8 @@ public:
         return String::format("%s %s", date_string().characters(), time_string().characters());
         return String::format("%s %s", date_string().characters(), time_string().characters());
     }
     }
 
 
+    String iso_date_string() const;
+
     // FIXME: One day, implement real locale support. Until then, everyone gets what the Clock MenuApplet displays.
     // FIXME: One day, implement real locale support. Until then, everyone gets what the Clock MenuApplet displays.
     String locale_date_string() const { return m_datetime.to_string("%Y-%m-%d"); }
     String locale_date_string() const { return m_datetime.to_string("%Y-%m-%d"); }
     String locale_string() const { return m_datetime.to_string(); }
     String locale_string() const { return m_datetime.to_string(); }

+ 10 - 0
Libraries/LibJS/Runtime/DatePrototype.cpp

@@ -67,6 +67,7 @@ void DatePrototype::initialize(GlobalObject& global_object)
     define_native_function("getSeconds", get_seconds, 0, attr);
     define_native_function("getSeconds", get_seconds, 0, attr);
     define_native_function("getTime", get_time, 0, attr);
     define_native_function("getTime", get_time, 0, attr);
     define_native_function("toDateString", to_date_string, 0, attr);
     define_native_function("toDateString", to_date_string, 0, attr);
+    define_native_function("toISOString", to_iso_string, 0, attr);
     define_native_function("toLocaleDateString", to_locale_date_string, 0, attr);
     define_native_function("toLocaleDateString", to_locale_date_string, 0, attr);
     define_native_function("toLocaleString", to_locale_string, 0, attr);
     define_native_function("toLocaleString", to_locale_string, 0, attr);
     define_native_function("toLocaleTimeString", to_locale_time_string, 0, attr);
     define_native_function("toLocaleTimeString", to_locale_time_string, 0, attr);
@@ -169,6 +170,15 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_date_string)
     return js_string(interpreter, move(string));
     return js_string(interpreter, move(string));
 }
 }
 
 
+JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_iso_string)
+{
+    auto* this_object = typed_this(interpreter, global_object);
+    if (!this_object)
+        return {};
+    auto string = this_object->iso_date_string();
+    return js_string(interpreter, move(string));
+}
+
 JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_date_string)
 JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_date_string)
 {
 {
     auto* this_object = typed_this(interpreter, global_object);
     auto* this_object = typed_this(interpreter, global_object);

+ 1 - 0
Libraries/LibJS/Runtime/DatePrototype.h

@@ -48,6 +48,7 @@ private:
     JS_DECLARE_NATIVE_FUNCTION(get_seconds);
     JS_DECLARE_NATIVE_FUNCTION(get_seconds);
     JS_DECLARE_NATIVE_FUNCTION(get_time);
     JS_DECLARE_NATIVE_FUNCTION(get_time);
     JS_DECLARE_NATIVE_FUNCTION(to_date_string);
     JS_DECLARE_NATIVE_FUNCTION(to_date_string);
+    JS_DECLARE_NATIVE_FUNCTION(to_iso_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_date_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_date_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_time_string);
     JS_DECLARE_NATIVE_FUNCTION(to_locale_time_string);

+ 9 - 0
Libraries/LibJS/Tests/builtins/Date/Date.prototype.toISOString.js

@@ -0,0 +1,9 @@
+test("basic functionality", () => {
+    expect(new Date(1597955034555).toISOString()).toBe("2020-08-20T20:23:54.555Z");
+
+    // FIXME: Add these once they work.
+    //expect(new Date(Date.UTC(22020)).toISOString()).toBe("+022020-01-01T00:00:00.000Z");
+    //expect(new Date(Date.UTC(1950)).toISOString()).toBe("1950-01-01T00:00:00.000Z");
+    //expect(new Date(Date.UTC(1800)).toISOString()).toBe("1800-01-01T00:00:00.000Z");
+    //expect(new Date(Date.UTC(-100)).toISOString()).toBe("-000100-01-01T00:00:00.000Z");
+});