From 1eac1b360bd0cacd7ff1a6fb933493ddb405b75a Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 20 Aug 2020 16:02:07 -0400 Subject: [PATCH] LibJS: Implement Date.UTC() --- Libraries/LibJS/Runtime/DateConstructor.cpp | 20 +++++++++++++++++++ Libraries/LibJS/Runtime/DateConstructor.h | 1 + .../LibJS/Tests/builtins/Date/Date.UTC.js | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 Libraries/LibJS/Tests/builtins/Date/Date.UTC.js diff --git a/Libraries/LibJS/Runtime/DateConstructor.cpp b/Libraries/LibJS/Runtime/DateConstructor.cpp index d66c0fa93b..b5f504c63b 100644 --- a/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -46,6 +46,7 @@ void DateConstructor::initialize(GlobalObject& global_object) define_property("length", Value(7), Attribute::Configurable); define_native_function("now", now, 0, Attribute::Writable | Attribute::Configurable); + define_native_function("UTC", utc, 1, Attribute::Writable | Attribute::Configurable); } DateConstructor::~DateConstructor() @@ -112,4 +113,23 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::now) return Value(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0); } +JS_DEFINE_NATIVE_FUNCTION(DateConstructor::utc) +{ + auto arg_or = [&interpreter](size_t i, i32 fallback) { return interpreter.argument_count() > i ? interpreter.argument(i).to_i32(interpreter) : fallback; }; + int year = interpreter.argument(0).to_i32(interpreter); + if (year >= 0 && year <= 99) + year += 1900; + + struct tm tm = {}; + tm.tm_year = year - 1900; + tm.tm_mon = arg_or(1, 0); // 0-based in both tm and JavaScript + tm.tm_mday = arg_or(2, 1); + tm.tm_hour = arg_or(3, 0); + tm.tm_min = arg_or(4, 0); + tm.tm_sec = arg_or(5, 0); + // timegm() doesn't read tm.tm_wday and tm.tm_yday, no need to fill them in. + + int milliseconds = arg_or(6, 0); + return Value(1000.0 * timegm(&tm) + milliseconds); +} } diff --git a/Libraries/LibJS/Runtime/DateConstructor.h b/Libraries/LibJS/Runtime/DateConstructor.h index 779338cab2..774f8e678f 100644 --- a/Libraries/LibJS/Runtime/DateConstructor.h +++ b/Libraries/LibJS/Runtime/DateConstructor.h @@ -45,6 +45,7 @@ private: virtual bool has_constructor() const override { return true; } JS_DECLARE_NATIVE_FUNCTION(now); + JS_DECLARE_NATIVE_FUNCTION(utc); }; } diff --git a/Libraries/LibJS/Tests/builtins/Date/Date.UTC.js b/Libraries/LibJS/Tests/builtins/Date/Date.UTC.js new file mode 100644 index 0000000000..171e537209 --- /dev/null +++ b/Libraries/LibJS/Tests/builtins/Date/Date.UTC.js @@ -0,0 +1,10 @@ +test("basic functionality", () => { + // FIXME: Years before 1970 don't work. Once they do, add a test. Also add a test with a year before 1900 then. + expect(Date.UTC(2020)).toBe(1577836800000); + expect(Date.UTC(2000, 10)).toBe(973036800000); + expect(Date.UTC(1980, 5, 30)).toBe(331171200000); + expect(Date.UTC(1980, 5, 30, 13)).toBe(331218000000); + expect(Date.UTC(1970, 5, 30, 13, 30)).toBe(15600600000); + expect(Date.UTC(1970, 0, 1, 0, 0, 59)).toBe(59000); + expect(Date.UTC(1970, 0, 1, 0, 0, 0, 999)).toBe(999); +});