diff --git a/Libraries/LibJS/Runtime/Date.cpp b/Libraries/LibJS/Runtime/Date.cpp index 3bc14b269bb..e50a925b003 100644 --- a/Libraries/LibJS/Runtime/Date.cpp +++ b/Libraries/LibJS/Runtime/Date.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -48,4 +49,36 @@ Date::~Date() { } +String Date::iso_date_string() const +{ + time_t timestamp = m_datetime.timestamp(); + struct tm tm; + gmtime_r(×tamp, &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(); +} + } diff --git a/Libraries/LibJS/Runtime/Date.h b/Libraries/LibJS/Runtime/Date.h index d97bcdbe3fc..cfd573875ea 100644 --- a/Libraries/LibJS/Runtime/Date.h +++ b/Libraries/LibJS/Runtime/Date.h @@ -52,6 +52,8 @@ public: 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. String locale_date_string() const { return m_datetime.to_string("%Y-%m-%d"); } String locale_string() const { return m_datetime.to_string(); } diff --git a/Libraries/LibJS/Runtime/DatePrototype.cpp b/Libraries/LibJS/Runtime/DatePrototype.cpp index b098ff47d3d..59b2948b248 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/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("getTime", get_time, 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("toLocaleString", to_locale_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)); } +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) { auto* this_object = typed_this(interpreter, global_object); diff --git a/Libraries/LibJS/Runtime/DatePrototype.h b/Libraries/LibJS/Runtime/DatePrototype.h index 7efb094623e..2c800f41216 100644 --- a/Libraries/LibJS/Runtime/DatePrototype.h +++ b/Libraries/LibJS/Runtime/DatePrototype.h @@ -48,6 +48,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(get_seconds); JS_DECLARE_NATIVE_FUNCTION(get_time); 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_string); JS_DECLARE_NATIVE_FUNCTION(to_locale_time_string); diff --git a/Libraries/LibJS/Tests/builtins/Date/Date.prototype.toISOString.js b/Libraries/LibJS/Tests/builtins/Date/Date.prototype.toISOString.js new file mode 100644 index 00000000000..f929540f995 --- /dev/null +++ b/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"); +});