diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/tests/non262/Date | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/Date')
55 files changed, 4938 insertions, 0 deletions
diff --git a/js/src/tests/non262/Date/15.9.4.2.js b/js/src/tests/non262/Date/15.9.4.2.js new file mode 100644 index 0000000000..684f7638fd --- /dev/null +++ b/js/src/tests/non262/Date/15.9.4.2.js @@ -0,0 +1,134 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 430930; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function iso(d) +{ + return new Date(d).toISOString(); +} + +function check(s, millis){ + description = "Date.parse('"+s+"') == '"+iso(millis)+"'"; + expected = millis; + actual = Date.parse(s); + reportCompare(expected, actual, description); +} + +function checkInvalid(s) +{ + description = "Date.parse('"+s+"') produces invalid date"; + expected = NaN; + actual = Date.parse(s); + reportCompare(expected, actual, description); +} + +function dd(year, month, day, hour, minute, second, millis){ + return Date.UTC(year, month-1, day, hour, minute, second, millis); +} + +function TZAtDate(d){ + return d.getTimezoneOffset() * 60000; +} + +function TZInMonth(month, year){ + return TZAtDate(new Date(dd(year,month,1,0,0,0,0))); +} + +function test() +{ + printBugNumber(BUGNUMBER); + + Jan1970TZ = TZInMonth(1, 1970); + Jan2009TZ = TZInMonth(1, 2009); + Jul2009TZ = TZInMonth(7, 2009); + CurrTZ = TZAtDate(new Date()); + + // formats with explicit timezone + check("2009-07-23T19:53:21.001+12:00", dd(2009,7,23,7,53,21,1)); + check("2009-07-23T19:53:21+12:00", dd(2009,7,23,7,53,21,0)); + check("2009-07-23T19:53+12:00", dd(2009,7,23,7,53,0,0)); + + check("2009-07T19:53:21.001+12:00", dd(2009,7,1,7,53,21,1)); + check("2009-07T19:53:21+12:00", dd(2009,7,1,7,53,21,0)); + check("2009-07T19:53+12:00", dd(2009,7,1,7,53,0,0)); + + check("2009T19:53:21.001+12:00", dd(2009,1,1,7,53,21,1)); + check("2009T19:53:21+12:00", dd(2009,1,1,7,53,21,0)); + check("2009T19:53+12:00", dd(2009,1,1,7,53,0,0)); + + checkInvalid("T19:53:21.001+12:00"); + checkInvalid("T19:53:21+12:00"); + checkInvalid("T19:53+12:00"); + + // formats without timezone uses the timezone as at that date + check("2009-07-23T19:53:21.001", dd(2009,7,23,19,53,21,1)+Jul2009TZ); + check("2009-07-23T19:53:21", dd(2009,7,23,19,53,21,0)+Jul2009TZ); + check("2009-07-23T19:53", dd(2009,7,23,19,53,0,0)+Jul2009TZ); + + check("2009-07T19:53:21.001", dd(2009,7,1,19,53,21,1)+Jul2009TZ); + check("2009-07T19:53:21", dd(2009,7,1,19,53,21,0)+Jul2009TZ); + check("2009-07T19:53", dd(2009,7,1,19,53,0,0)+Jul2009TZ); + + check("2009T19:53:21.001", dd(2009,1,1,19,53,21,1)+Jan2009TZ); + check("2009T19:53:21", dd(2009,1,1,19,53,21,0)+Jan2009TZ); + check("2009T19:53", dd(2009,1,1,19,53,0,0)+Jan2009TZ); + + checkInvalid("T19:53:21.001"); + checkInvalid("T19:53:21"); + checkInvalid("T19:53"); + + // with no time at all assume UTC + check("2009-07-23", dd(2009,7,23,0,0,0,0)); + check("2009-07", dd(2009,7,1,0,0,0,0)); + check("2009", dd(2009,1,1,0,0,0,0)); + + // one field too big + checkInvalid("2009-13-23T19:53:21.001+12:00"); + checkInvalid("2009-07-32T19:53:21.001+12:00"); + checkInvalid("2009-07-23T25:53:21.001+12:00"); + checkInvalid("2009-07-23T19:60:21.001+12:00"); + checkInvalid("2009-07-23T19:53:60.001+12:00"); + checkInvalid("2009-07-23T19:53:21.001+24:00"); + checkInvalid("2009-07-23T19:53:21.001+12:60"); + + // other month ends + check("2009-06-30T19:53:21.001+12:00", dd(2009,6,30,7,53,21,1)); + checkInvalid("2009-06-31T19:53:21.001+12:00"); + check("2009-02-28T19:53:21.001+12:00", dd(2009,2,28,7,53,21,1)); + checkInvalid("2009-02-29T19:53:21.001+12:00"); + check("2008-02-29T19:53:21.001+12:00", dd(2008,2,29,7,53,21,1)); + checkInvalid("2008-02-30T19:53:21.001+12:00"); + + // limits of representation + checkInvalid("-271821-04-19T23:59:59.999Z"); + check("-271821-04-20", -8.64e15); + check("+275760-09-13", 8.64e15); + checkInvalid("+275760-09-13T00:00:00.001Z"); + + check("-269845-07-23T19:53:21.001+12:00", dd(-269845,7,23,7,53,21,1)); + check("+273785-07-23T19:53:21.001+12:00", dd(273785,7,23,7,53,21,1)); + + // explicit UTC + check("2009-07-23T19:53:21.001Z", dd(2009,7,23,19,53,21,1)); + check("+002009-07-23T19:53:21.001Z", dd(2009,7,23,19,53,21,1)); + + // different timezones + check("2009-07-23T19:53:21.001+12:00", dd(2009,7,23,7,53,21,1)); + check("2009-07-23T00:53:21.001-07:00", dd(2009,7,23,7,53,21,1)); + + // 00:00 and 24:00 + check("2009-07-23T00:00:00.000-07:00", dd(2009,7,23,7,0,0,0)); + check("2009-07-23T24:00:00.000-07:00", dd(2009,7,24,7,0,0,0)); + + // Bug 730838 - non-zero fraction part for midnight should produce NaN + checkInvalid("1970-01-01T24:00:00.500Z"); +} diff --git a/js/src/tests/non262/Date/15.9.5.5-02.js b/js/src/tests/non262/Date/15.9.5.5-02.js new file mode 100644 index 0000000000..07623e675c --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.5-02.js @@ -0,0 +1,63 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 398485; +var summary = 'Date.prototype.toLocaleString should not clamp year'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d; + var y; + var l; + var maxms = 8640000000000000; + + d = new Date(-maxms ); + y = d.getFullYear(); + + actual = y; + expect = -271821; + reportCompare(expect, actual, summary + ': check year'); + + l = d.toLocaleString(); + print(l); + if (this.hasOwnProperty("Intl")) { + // ECMA-402 specifies that toLocaleString uses a proleptic Gregorian + // calender without year 0. + // Also, localized strings usually use era indicators such as "BC" + // instead of minus signs. + expect = Math.abs(y - 1) + ''; + } else { + // ECMA-262 up to edition 5.1 didn't specify toLocaleString; + // the previous implementation assumed a calendar with year 0 and used + // minus sign. + expect = y + ''; + } + actual = l.match(/-?[0-9]{3,}/) + ''; + reportCompare(expect, actual, summary + ': check toLocaleString'); + + d = new Date(maxms ); + y = d.getFullYear(); + l = d.toLocaleString(); + print(l); + + actual = y; + expect = 275760; + reportCompare(expect, actual, summary + ': check year'); + + actual = l.match(new RegExp(y)) + ''; + expect = y + ''; + reportCompare(expect, actual, summary + ': check toLocaleString'); +} diff --git a/js/src/tests/non262/Date/15.9.5.5.js b/js/src/tests/non262/Date/15.9.5.5.js new file mode 100644 index 0000000000..1a21b33a63 --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.5.js @@ -0,0 +1,111 @@ +// |reftest| random-if(xulRuntime.OS=="Linux") +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.9.5.5.js + ECMA Section: 15.9.5.5 Date.prototype.toLocaleString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "date" + portion of the Date in the current time zone in a convenient, + human-readable form. We can't test the content of the string, + but can verify that the string is parsable by Date.parse + + The toLocaleString function is not generic; it generates a runtime error + if its 'this' value is not a Date object. Therefore it cannot be transferred + to other kinds of objects for use as a method. + + Note: This test isn't supposed to work with a non-English locale per spec. + + Author: pschwartau@netscape.com + Date: 14 november 2000 +*/ + +var SECTION = "15.9.5.5"; +var TITLE = "Date.prototype.toLocaleString()"; + +var status = ''; +var actual = ''; +var expect = ''; + + +writeHeaderToLog( SECTION + " "+ TITLE); + +var now = new Date(); + +// first, some generic tests - + +status = "typeof (now.toLocaleString())"; +actual = typeof (now.toLocaleString()); +expect = "string"; +addTestCase(); + +status = "Date.prototype.toLocaleString.length"; +actual = Date.prototype.toLocaleString.length; +expect = 0; +addTestCase(); + +// Date.parse is accurate to the second; valueOf() to the millisecond - +status = "Math.abs(Date.parse(now.toLocaleString('en-US')) - now.valueOf()) < 1000"; +actual = Math.abs(Date.parse(now.toLocaleString('en-US')) - now.valueOf()) < 1000; +expect = true; +addTestCase(); + + + +// 1970 +addDateTestCase(0); +addDateTestCase(TZ_ADJUST); + + +// 1900 +addDateTestCase(UTC_01_JAN_1900); +addDateTestCase(UTC_01_JAN_1900 -TZ_ADJUST); + + +// 2000 +addDateTestCase(UTC_01_JAN_2000); +addDateTestCase(UTC_01_JAN_2000 -TZ_ADJUST); + + +// 29 Feb 2000 +addDateTestCase(UTC_29_FEB_2000); +addDateTestCase(UTC_29_FEB_2000 - 1000); +addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + + +// 2005 +addDateTestCase(UTC_01_JAN_2005); +addDateTestCase(UTC_01_JAN_2005 - 1000); +addDateTestCase(UTC_01_JAN_2005-TZ_ADJUST); + + + +//----------------------------------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------------------------------- + + +function addTestCase() +{ + AddTestCase( + status, + expect, + actual); +} + + +function addDateTestCase(date_given_in_milliseconds) +{ + var givenDate = new Date(date_given_in_milliseconds); + + status = 'Date.parse(' + givenDate + ').toLocaleString("en-US"))'; + actual = Date.parse(givenDate.toLocaleString("en-US")); + expect = date_given_in_milliseconds; + addTestCase(); +} + diff --git a/js/src/tests/non262/Date/15.9.5.6.js b/js/src/tests/non262/Date/15.9.5.6.js new file mode 100644 index 0000000000..67e67630ec --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.6.js @@ -0,0 +1,118 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.9.5.6.js + ECMA Section: 15.9.5.6 Date.prototype.toLocaleDateString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "date" + portion of the Date in the current time zone in a convenient, + human-readable form. We can't test the content of the string, + but can verify that the string is parsable by Date.parse + + The toLocaleDateString function is not generic; it generates a runtime error + if its 'this' value is not a Date object. Therefore it cannot be transferred + to other kinds of objects for use as a method. + + Note: This test isn't supposed to work with a non-English locale per spec. + + Author: pschwartau@netscape.com + Date: 14 november 2000 +*/ + +var SECTION = "15.9.5.6"; +var TITLE = "Date.prototype.toLocaleDateString()"; + +var status = ''; +var actual = ''; +var expect = ''; + + +writeHeaderToLog( SECTION + " "+ TITLE); + +var now = new Date(); + +// first, some generic tests - + +status = "typeof (now.toLocaleDateString())"; +actual = typeof (now.toLocaleDateString()); +expect = "string"; +addTestCase(); + +status = "Date.prototype.toLocaleDateString.length"; +actual = Date.prototype.toLocaleDateString.length; +expect = 0; +addTestCase(); + +/* Date.parse is accurate to the second; valueOf() to the millisecond. + Here we expect them to coincide, as we expect a time of exactly midnight - */ +status = "(Date.parse(now.toLocaleDateString('en-US')) - (midnight(now)).valueOf()) == 0"; +actual = (Date.parse(now.toLocaleDateString('en-US')) - (midnight(now)).valueOf()) == 0; +expect = true; +addTestCase(); + + + +// 1970 +addDateTestCase(0); +addDateTestCase(TZ_ADJUST); + + +// 1900 +addDateTestCase(UTC_01_JAN_1900); +addDateTestCase(UTC_01_JAN_1900 - TZ_ADJUST); + + +// 2000 +addDateTestCase(UTC_01_JAN_2000); +addDateTestCase(UTC_01_JAN_2000 - TZ_ADJUST); + + +// 29 Feb 2000 +addDateTestCase(UTC_29_FEB_2000); +addDateTestCase(UTC_29_FEB_2000 - 1000); +addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + + +// 2005 +addDateTestCase(UTC_01_JAN_2005); +addDateTestCase(UTC_01_JAN_2005 - 1000); +addDateTestCase(UTC_01_JAN_2005 - TZ_ADJUST); + + + +//----------------------------------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------------------------------- + + +function addTestCase() +{ + new TestCase( + status, + expect, + actual); +} + + +function addDateTestCase(date_given_in_milliseconds) +{ + var givenDate = new Date(date_given_in_milliseconds); + + status = 'Date.parse(' + givenDate + ').toLocaleDateString("en-US"))'; + actual = Date.parse(givenDate.toLocaleDateString("en-US")); + expect = Date.parse(midnight(givenDate)); + addTestCase(); +} + + +function midnight(givenDate) +{ + // midnight on the given date - + return new Date(givenDate.getFullYear(), givenDate.getMonth(), givenDate.getDate()); +} + diff --git a/js/src/tests/non262/Date/15.9.5.7.js b/js/src/tests/non262/Date/15.9.5.7.js new file mode 100644 index 0000000000..61ebf72fee --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.7.js @@ -0,0 +1,111 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + File Name: 15.9.5.7.js + ECMA Section: 15.9.5.7 Date.prototype.toLocaleTimeString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "time" + portion of the Date in the current time zone in a convenient, + human-readable form. We test the content of the string by checking + that + + new Date(d.toDateString() + " " + d.toLocaleTimeString()) == d + + Author: pschwartau@netscape.com + Date: 14 november 2000 + Revised: 07 january 2002 because of a change in JS Date format: + Revised: 21 November 2005 since the string comparison stuff is horked. + bclary + + See http://bugzilla.mozilla.org/show_bug.cgi?id=118266 (SpiderMonkey) + See http://bugzilla.mozilla.org/show_bug.cgi?id=118636 (Rhino) +*/ +//----------------------------------------------------------------------------- +var SECTION = "15.9.5.7"; +var TITLE = "Date.prototype.toLocaleTimeString()"; + +var status = ''; +var actual = ''; +var expect = ''; +var givenDate; +var year = ''; +var regexp = ''; +var TimeString = ''; +var reducedDateString = ''; +var hopeThisIsLocaleTimeString = ''; +var cnERR ='OOPS! FATAL ERROR: no regexp match in extractLocaleTimeString()'; + +writeHeaderToLog( SECTION + " "+ TITLE); + +var now = new Date(); + +// valueOf() is to accurate to the millisecond, +// Date.parse() is accurate only to the second +var TIME_NOW = now.valueOf(); + +// first, a couple generic tests - + +status = "typeof (now.toLocaleTimeString())"; +actual = typeof (now.toLocaleTimeString()); +expect = "string"; +addTestCase(); + +status = "Date.prototype.toLocaleTimeString.length"; +actual = Date.prototype.toLocaleTimeString.length; +expect = 0; +addTestCase(); + +// 1970 +addDateTestCase(0); +addDateTestCase(TZ_ADJUST); + +// 1900 +addDateTestCase(UTC_01_JAN_1900); +addDateTestCase(UTC_01_JAN_1900 - TZ_ADJUST); + +// 2000 +addDateTestCase(UTC_01_JAN_2000); +addDateTestCase(UTC_01_JAN_2000 - TZ_ADJUST); + +// 29 Feb 2000 +addDateTestCase(UTC_29_FEB_2000); +addDateTestCase(UTC_29_FEB_2000 - 1000); +addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + +// Now +addDateTestCase( TIME_NOW); +addDateTestCase( TIME_NOW - TZ_ADJUST); + +// 2005 +addDateTestCase(UTC_01_JAN_2005); +addDateTestCase(UTC_01_JAN_2005 - 1000); +addDateTestCase(UTC_01_JAN_2005 - TZ_ADJUST); + +test(); + +function addTestCase() +{ + new TestCase( + status, + expect, + actual); +} + + +function addDateTestCase(date_given_in_milliseconds) +{ + var s = 'new Date(' + date_given_in_milliseconds + ')'; + givenDate = new Date(date_given_in_milliseconds); + + status = 'd = ' + s + + '; d == new Date(d.toDateString() + " " + d.toLocaleTimeString())'; + expect = givenDate.toString(); + actual = new Date(givenDate.toDateString() + + ' ' + givenDate.toLocaleTimeString()).toString(); + addTestCase(); +} + diff --git a/js/src/tests/non262/Date/UTC-convert-all-arguments.js b/js/src/tests/non262/Date/UTC-convert-all-arguments.js new file mode 100644 index 0000000000..2fee8b951d --- /dev/null +++ b/js/src/tests/non262/Date/UTC-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "Date.UTC must convert *all* arguments to number, not return NaN early if " + + "a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var args = + [ + [bad], + + [NaN, bad], + [Infinity, bad], + [1970, bad], + + [1970, NaN, bad], + [1970, Infinity, bad], + [1970, 4, bad], + + [1970, 4, NaN, bad], + [1970, 4, Infinity, bad], + [1970, 4, 17, bad], + + [1970, 4, 17, NaN, bad], + [1970, 4, 17, Infinity, bad], + [1970, 4, 17, 13, bad], + + [1970, 4, 17, 13, NaN, bad], + [1970, 4, 17, 13, Infinity, bad], + [1970, 4, 17, 13, 37, bad], + + [1970, 4, 17, 13, 37, NaN, bad], + [1970, 4, 17, 13, 37, Infinity, bad], + [1970, 4, 17, 13, 37, 23, bad], + ]; + +for (var i = 0, len = args.length; i < len; i++) + expectThrowTypeError(function() { Date.UTC.apply(null, args[i]); }, i); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/browser.js b/js/src/tests/non262/Date/browser.js new file mode 100644 index 0000000000..e2c7f6d317 --- /dev/null +++ b/js/src/tests/non262/Date/browser.js @@ -0,0 +1,12 @@ +if (typeof getDefaultLocale === "undefined") { + var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale; +} +if (typeof setDefaultLocale === "undefined") { + var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale; +} +if (typeof getTimeZone === "undefined") { + var getTimeZone = SpecialPowers.Cu.getJSTestingFunctions().getTimeZone; +} +if (typeof setTimeZone === "undefined") { + var setTimeZone = SpecialPowers.Cu.getJSTestingFunctions().setTimeZone; +} diff --git a/js/src/tests/non262/Date/constructor-convert-all-arguments.js b/js/src/tests/non262/Date/constructor-convert-all-arguments.js new file mode 100644 index 0000000000..3a281cae22 --- /dev/null +++ b/js/src/tests/non262/Date/constructor-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "new Date(...) must convert *all* arguments to number, not return NaN " + + "early if a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var funcs = + [ + function() { new Date(bad); }, + + function() { new Date(NaN, bad); }, + function() { new Date(Infinity, bad); }, + function() { new Date(1970, bad); }, + + function() { new Date(1970, NaN, bad); }, + function() { new Date(1970, Infinity, bad); }, + function() { new Date(1970, 4, bad); }, + + function() { new Date(1970, 4, NaN, bad); }, + function() { new Date(1970, 4, Infinity, bad); }, + function() { new Date(1970, 4, 17, bad); }, + + function() { new Date(1970, 4, 17, NaN, bad); }, + function() { new Date(1970, 4, 17, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, bad); }, + + function() { new Date(1970, 4, 17, 13, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, bad); }, + + function() { new Date(1970, 4, 17, 13, 37, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, 37, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, 23, bad); }, + ]; + +for (var i = 0, len = funcs.length; i < len; i++) + expectThrowTypeError(funcs[i]); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/constructor-one-Date-argument.js b/js/src/tests/non262/Date/constructor-one-Date-argument.js new file mode 100644 index 0000000000..718c413731 --- /dev/null +++ b/js/src/tests/non262/Date/constructor-one-Date-argument.js @@ -0,0 +1,40 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1187233; +var summary = + "Passing a Date object to |new Date()| should copy it, not convert it to " + + "a primitive and create it from that."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +Date.prototype.toString = Date.prototype.valueOf = null; +var d = new Date(new Date(8675309)); +assertEq(d.getTime(), 8675309); + +Date.prototype.valueOf = () => 42; +d = new Date(new Date(8675309)); +assertEq(d.getTime(), 8675309); + +var D = newGlobal().Date; + +D.prototype.toString = D.prototype.valueOf = null; +var d = new Date(new D(3141592654)); +assertEq(d.getTime(), 3141592654); + +D.prototype.valueOf = () => 525600; +d = new Date(new D(3141592654)); +assertEq(d.getTime(), 3141592654); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/constructor-one-argument.js b/js/src/tests/non262/Date/constructor-one-argument.js new file mode 100644 index 0000000000..d7acd33aad --- /dev/null +++ b/js/src/tests/non262/Date/constructor-one-argument.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 738511; +var summary = + "new Date(value) should call ToPrimitive on value before testing for " + + "string-ness"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(new Date(new String("2012-01-31T00:00:00.000Z")).valueOf(), + 1327968000000, + "Date constructor passed a String object should parse it"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/dashed-date.js b/js/src/tests/non262/Date/dashed-date.js new file mode 100644 index 0000000000..a1babf991e --- /dev/null +++ b/js/src/tests/non262/Date/dashed-date.js @@ -0,0 +1,118 @@ +const tests = [ + // ==== Date only ==== + + // dd-MMM-yyyy + ["24-Apr-2023", "2023-04-24T00:00:00"], + ["24-apr-2023", "2023-04-24T00:00:00"], + ["24-April-2023", "2023-04-24T00:00:00"], + ["24-APRIL-2023", "2023-04-24T00:00:00"], + ["24-Apr-2033", "2033-04-24T00:00:00"], + + ["24-Apr-0023", "0023-04-24T00:00:00"], + + // dd-MMM-yy + ["24-Apr-23", "2023-04-24T00:00:00"], + ["24-Apr-33", "2033-04-24T00:00:00"], + + // dd-MMM-yyy + ["24-Apr-023", "2023-04-24T00:00:00"], + + // yyyy-MM-dd + ["2023-Apr-24", "2023-04-24T00:00:00"], + ["2033-Apr-24", "2033-04-24T00:00:00"], + + // yy-MM-dd + ["33-Apr-24", "2033-04-24T00:00:00"], + + // yyy-MM-dd + ["033-Apr-24", "2033-04-24T00:00:00"], + + // ==== Date followed by hour and TZ ==== + + ["24-Apr-2023 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023 Mon 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023 (Mon) 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023(Mon)12:34:56", "2023-04-24T12:34:56"], + + ["24-Apr-2023,12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023,Mon 12:34:56", "2023-04-24T12:34:56"], + + ["24-Apr-2023 12:34:56 GMT", "2023-04-24T12:34:56Z"], + ["24-Apr-2023 12:34:56 +04", "2023-04-24T12:34:56+04:00"], + ["24-Apr-2023 12:34:56 +04:30", "2023-04-24T12:34:56+04:30"], + ["24-Apr-2023 12:34:56 -04", "2023-04-24T12:34:56-04:00"], + ["24-Apr-2023 12:34:56 -04:30", "2023-04-24T12:34:56-04:30"], + + ["24-Apr-2023 GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023 +04", "2023-04-24T00:00:00+04:00"], + ["24-Apr-2023 +04:30", "2023-04-24T00:00:00+04:30"], + ["24-Apr-2023 -04", "2023-04-24T00:00:00-04:00"], + ["24-Apr-2023 -04:30", "2023-04-24T00:00:00-04:30"], + + ["24-Apr-2023GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023+04", "2023-04-24T00:00:00+04:00"], + ["24-Apr-2023+04:30", "2023-04-24T00:00:00+04:30"], + ["24-Apr-2023-04", "2023-04-24T00:00:00-04:00"], + ["24-Apr-2023-04:30", "2023-04-24T00:00:00-04:30"], + + ["24-Apr-2023,GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023,+04", "2023-04-24T00:00:00+04:00"], + ["24-Apr-2023,+04:30", "2023-04-24T00:00:00+04:30"], + ["24-Apr-2023,-04", "2023-04-24T00:00:00-04:00"], + ["24-Apr-2023,-04:30", "2023-04-24T00:00:00-04:30"], + + ["24-Apr-2023/12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023/GMT", "2023-04-24T00:00:00Z"], + + // ==== non dd-MMM-yyyy. Uses fallback path ==== + + // Missing space. + ["24-Apr-202312:13:14", "-202312-04-24T13:14:00"], + + // Extra delimiter. + ["24-Apr- 2023", "2023-04-24T00:00:00"], + ["24-Apr -2023", "-002023-04-24T00:00:00"], + ["24- Apr-2023", "-002023-04-24T00:00:00"], + ["24 -Apr-2023", "-002023-04-24T00:00:00"], + + ["24-Apr-/2023", "2023-04-24T00:00:00"], + ["24-Apr/-2023", "-002023-04-24T00:00:00"], + ["24-/Apr-2023", "-002023-04-24T00:00:00"], + ["24/-Apr-2023", "-002023-04-24T00:00:00"], + + ["24-Apr-()2023", "2023-04-24T00:00:00"], + ["24-Apr()-2023", "-002023-04-24T00:00:00"], + ["24-()Apr-2023", "-002023-04-24T00:00:00"], + ["24()-Apr-2023", "-002023-04-24T00:00:00"], + + // mday being 3+ digits + ["024-Apr-2023", "-002023-04-24T00:00:00"], + ["0024-Apr-2023", "-002023-04-24T00:00:00"], +]; + +for (const [testString, isoString] of tests) { + const testDate = new Date(testString); + const isoDate = new Date(isoString); + + assertEq(testDate.getTime(), isoDate.getTime(), + testString); +} + +const invalidTests = [ + // mday being out of range. + "32-01-32", + + // mday being 3+ digits, while year being 2-3 digits. + "024-Apr-22", + "024-Apr-023", + + // Duplicate date. + "2012-Apr-08 12/12/12", +]; + +for (const testString of invalidTests) { + assertEq(Number.isNaN(new Date(testString).getTime()), true, testString); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/defaultvalue.js b/js/src/tests/non262/Date/defaultvalue.js new file mode 100644 index 0000000000..2fc5887d18 --- /dev/null +++ b/js/src/tests/non262/Date/defaultvalue.js @@ -0,0 +1,190 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 645464; +var summary = + "[[DefaultValue]] behavior wrong for Date with overridden valueOf/toString"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function allTests() +{ + var DS = new Date(2010, 1, 1).toString(); + + // equality + + var d = new Date(2010, 1, 1); + assertEq(d == DS, true); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d2 == DS, true); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 42; }; + assertEq(d3 == 42, true); + + function testEquality() + { + var d = new Date(2010, 1, 1); + assertEq(d == DS, true); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d2 == DS, true); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 42; }; + assertEq(d3 == 42, true); + } + testEquality(); + + + // addition of Date to number + + var d = new Date(2010, 1, 1); + assertEq(d + 5, DS + "5"); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 9; }; + assertEq(d2 + 3, 9 + 3); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d3 + 5, DS + "5"); + + function testDateNumberAddition() + { + var d = new Date(2010, 1, 1); + assertEq(d + 5, DS + "5"); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 9; }; + assertEq(d2 + 3, 9 + 3); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d3 + 5, DS + "5"); + } + testDateNumberAddition(); + + + // addition of Date to Date + + var d = new Date(2010, 1, 1); + assertEq(d + d, DS + DS); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 5; }; + assertEq(d2 + d2, 10); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 8.5; }; + assertEq(d3 + d3, DS + DS); + + function testDateDateAddition() + { + var d = new Date(2010, 1, 1); + assertEq(d + d, DS + DS); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 5; }; + assertEq(d2 + d2, 10); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 8.5; }; + assertEq(d3 + d3, DS + DS); + } + testDateDateAddition(); + + + // Date as bracketed property name + + var obj = { 8: 42, 9: 73 }; + obj[DS] = 17; + + var d = new Date(2010, 1, 1); + assertEq(obj[d], 17); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 8; } + assertEq(obj[d2], 17); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 9; }; + assertEq(obj[d3], 73); + + function testPropertyName() + { + var obj = { 8: 42, 9: 73 }; + obj[DS] = 17; + + var d = new Date(2010, 1, 1); + assertEq(obj[d], 17); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 8; } + assertEq(obj[d2], 17); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 9; }; + assertEq(obj[d3], 73); + } + testPropertyName(); + + + // Date as property name with |in| operator + + var obj = {}; + obj[DS] = 5; + + var d = new Date(2010, 1, 1); + assertEq(d in obj, true); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return "baz"; }; + assertEq(d2 in { baz: 42 }, true); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return "quux"; }; + assertEq(d3 in obj, true); + + function testInOperatorName() + { + var obj = {}; + obj[DS] = 5; + + var d = new Date(2010, 1, 1); + assertEq(d in obj, true); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return "baz"; }; + assertEq(d2 in { baz: 42 }, true); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return "quux"; }; + assertEq(d3 in obj, true); + } + testInOperatorName(); +} + +allTests(); + +if (typeof newGlobal === "function") +{ + Date = newGlobal().Date; + allTests(); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js new file mode 100644 index 0000000000..95a88e9a92 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(1, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js new file mode 100644 index 0000000000..0810f91176 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(2, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js new file mode 100644 index 0000000000..a70559afa3 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(3, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js new file mode 100644 index 0000000000..3bda28d617 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(4, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js new file mode 100644 index 0000000000..a15692ff0d --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(5, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js new file mode 100644 index 0000000000..d2ce8e90c8 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(6, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js new file mode 100644 index 0000000000..aaa560c202 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(7, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js new file mode 100644 index 0000000000..30a6f781b8 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(8, 8); diff --git a/js/src/tests/non262/Date/equality-to-boolean.js b/js/src/tests/non262/Date/equality-to-boolean.js new file mode 100644 index 0000000000..c60319b9d9 --- /dev/null +++ b/js/src/tests/non262/Date/equality-to-boolean.js @@ -0,0 +1,39 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +print("Test for correct implementation of |Date == boolean| and vice versa"); + +/************** + * BEGIN TEST * + **************/ + +Date.prototype.toString = function() { return 1; }; +Date.prototype.valueOf = function() { return 0; }; + +/* + * ES5 11.9.3 doesn't directly handle obj == boolean. Instead it translates it + * as follows: + * + * obj == boolean + * ↳ obj == ToNumber(boolean), per step 7 + * ↳ ToPrimitive(obj) == ToNumber(boolean), per step 9 + * + * ToPrimitive calls [[DefaultValue]] with no hint. For Date objects this is + * treated as if it were instead called with hint String. That calls toString, + * which returns 1, so Date objects here should compare equal to true and + * unequal to false. + */ +assertEq(new Date == true, true); +assertEq(new Date == false, false); + +/* == is symmetric. */ +assertEq(true == new Date, true); +assertEq(false == new Date, false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/fractions.js b/js/src/tests/non262/Date/fractions.js new file mode 100644 index 0000000000..30dd663ddd --- /dev/null +++ b/js/src/tests/non262/Date/fractions.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 771946; +var summary = "Fractional days, months, years shouldn't trigger asserts"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +new Date(0).setFullYear(1.5); +new Date(0).setUTCDate(1.5); +new Date(0).setMonth(1.5); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/non-iso.js b/js/src/tests/non262/Date/non-iso.js new file mode 100644 index 0000000000..9bd97dc288 --- /dev/null +++ b/js/src/tests/non262/Date/non-iso.js @@ -0,0 +1,81 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +/* + * For the sake of cross compatibility with other implementations we + * follow the W3C "NOTE-datetime" specification when parsing dates of + * the form YYYY-MM-DDTHH:MM:SS save for a few exceptions: months, days, hours + * minutes, and seconds may be either one _or_ two digits long, and the 'T' + * preceding the time part may be replaced with a space. So, a string like + * "1997-3-8 1:1:1" will parse successfully. See bug: 1203298 + */ + +/************** + * BEGIN TEST * + **************/ + +assertEq(new Date("1997-03-08 1:1:1.01").getTime(), + new Date("1997-03-08T01:01:01.01").getTime()); +assertEq(new Date("1997-03-08 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-3-08 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-3-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("+001997-3-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("+001997-03-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-03-08 11:19").getTime(), + new Date("1997-03-08T11:19").getTime()); +assertEq(new Date("1997-03-08 1:19").getTime(), + new Date("1997-03-08T01:19").getTime()); +assertEq(new Date("1997-03-08 1:1").getTime(), + new Date("1997-03-08T01:01").getTime()); +assertEq(new Date("1997-03-08 1:1:01").getTime(), + new Date("1997-03-08T01:01:01").getTime()); +assertEq(new Date("1997-03-08 1:1:1").getTime(), + new Date("1997-03-08T01:01:01").getTime()); +assertEq(new Date("1997-03-08 11").getTime(), + new Date("1997-03-08T11").getTime()); // Date(NaN) +assertEq(new Date("1997-03-08").getTime(), + new Date("1997-03-08").getTime()); +assertEq(new Date("1997-03-8").getTime(), + new Date("1997-03-08").getTime()); +assertEq(new Date("1997-3-8").getTime(), + new Date("1997-03-08").getTime()); +assertEq(new Date("1997-03-08 11:19:10-07").getTime(), + new Date("1997-03-08 11:19:10-0700").getTime()); +assertEq(new Date("1997-03-08T11:19:10-07").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-3-8 ").getTime(), + new Date("1997-03-08T").getTime()); // Date(NaN) +assertEq(new Date("1997-3-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("+001997-3-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("+001997-3-08T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-3-8 :00:01").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-3-8 01::01").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:19").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1:01").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1:1").getTime(), + new Date(NaN).getTime()); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/parse-from-tostring-methods.js b/js/src/tests/non262/Date/parse-from-tostring-methods.js new file mode 100644 index 0000000000..b6bf577bb0 --- /dev/null +++ b/js/src/tests/non262/Date/parse-from-tostring-methods.js @@ -0,0 +1,31 @@ +let dates = [ + "0041-09-23", "+000041-09-23", "-000041-09-23", + "0091-09-23", "+000091-09-23", "-000091-09-23", + "0217-09-23", "+000217-09-23", "-000217-09-23", + "2017-09-23", "+002017-09-23", "-002017-09-23", + "+022017-09-23", "-022017-09-23", + "+202017-09-23", "-202017-09-23", +]; + +for (let date of dates) { + let d = new Date(date); + let timeValue = d.valueOf(); + + assertEq(Number.isNaN(timeValue), false, `Cannot parse "${date}" as ISO date-only form`); + + // Ensure parsing the results of toString(), toUTCString(), and toISOString() + // gives the same time value as required by 20.3.3.2 Date.parse. + // + // Additional requirement not present in ES2019 draft rev 7acacc524213058a2368b5fa751fac7ea08ba230: + // The time zone offset must not contain seconds (or milliseconds) for |Date.parse(x.toString())| + // to be equal to |x.valueOf()|. + let tz = d.getTimezoneOffset(); + if (Math.trunc(tz) === tz) { + assertEq(Date.parse(d.toString()), timeValue, `Cannot parse from toString() of "${date}"`); + } + assertEq(Date.parse(d.toUTCString()), timeValue, `Cannot parse from toUTCString() of "${date}"`); + assertEq(Date.parse(d.toISOString()), timeValue, `Cannot parse from toISOString() of "${date}"`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-time-zone.js b/js/src/tests/non262/Date/parse-time-zone.js new file mode 100644 index 0000000000..c239822b04 --- /dev/null +++ b/js/src/tests/non262/Date/parse-time-zone.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +// bug 1676708 +inTimeZone("Europe/London", () => { + let dt = new Date("Wed Nov 11 2020 19:18:50 GMT+0010"); + assertEq(dt.getTime(), new Date(2020, Month.November, 11, 19, 08, 50).getTime()); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/prototype-is-not-a-date.js b/js/src/tests/non262/Date/prototype-is-not-a-date.js new file mode 100644 index 0000000000..26f0c3e859 --- /dev/null +++ b/js/src/tests/non262/Date/prototype-is-not-a-date.js @@ -0,0 +1,15 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 861219; +var summary = "Date.prototype isn't an instance of Date"; + +print(BUGNUMBER + ": " + summary); + +assertEq(Date.prototype instanceof Date, false); +assertEq(Date.prototype.__proto__, Object.prototype); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/regress-188211.js b/js/src/tests/non262/Date/regress-188211.js new file mode 100644 index 0000000000..663611b81b --- /dev/null +++ b/js/src/tests/non262/Date/regress-188211.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 188211; +var summary = 'Date.prototype.toLocaleString() error on future dates'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var dt; + +dt = new Date(208e10); +printStatus(dt+''); +expect = true; +actual = dt.toLocaleString().indexOf('2035') >= 0; +reportCompare(expect, actual, summary + ': new Date(208e10)'); + +dt = new Date(209e10); +printStatus(dt+''); +expect = true; +actual = dt.toLocaleString().indexOf('2036') >= 0; +reportCompare(expect, actual, summary + ': new Date(209e10)'); diff --git a/js/src/tests/non262/Date/regress-301738-01.js b/js/src/tests/non262/Date/regress-301738-01.js new file mode 100644 index 0000000000..8f5ae7d304 --- /dev/null +++ b/js/src/tests/non262/Date/regress-301738-01.js @@ -0,0 +1,97 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 301738; +var summary = 'Date parse compatibilty with MSIE'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +/* + Case 1. The input string contains an English month name. + The form of the string can be month f l, or f month l, or + f l month which each evaluate to the same date. + If f and l are both greater than or equal to 70, or + both less than 70, the date is invalid. + The year is taken to be the greater of the values f, l. + If the year is greater than or equal to 70 and less than 100, + it is considered to be the number of years after 1900. +*/ + +var month = 'January'; +var f; +var l; + +f = l = 0; +expect = true; + +actual = isNaN(new Date(month + ' ' + f + ' ' + l)); +reportCompare(expect, actual, 'January 0 0 is invalid'); + +actual = isNaN(new Date(f + ' ' + l + ' ' + month)); +reportCompare(expect, actual, '0 0 January is invalid'); + +actual = isNaN(new Date(f + ' ' + month + ' ' + l)); +reportCompare(expect, actual, '0 January 0 is invalid'); + +f = l = 70; + +actual = isNaN(new Date(month + ' ' + f + ' ' + l)); +reportCompare(expect, actual, 'January 70 70 is invalid'); + +actual = isNaN(new Date(f + ' ' + l + ' ' + month)); +reportCompare(expect, actual, '70 70 January is invalid'); + +actual = isNaN(new Date(f + ' ' + month + ' ' + l)); +reportCompare(expect, actual, '70 January 70 is invalid'); + +f = 100; +l = 15; + +// year, month, day +expect = new Date(f, 0, l).toString(); + +actual = new Date(month + ' ' + f + ' ' + l).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = new Date(f + ' ' + l + ' ' + month).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = new Date(f + ' ' + month + ' ' + l).toString(); +reportCompare(expect, actual, 'f month l'); + +f = 80; +l = 15; + +// year, month, day +expect = (new Date(f, 0, l)).toString(); + +actual = (new Date(month + ' ' + f + ' ' + l)).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = (new Date(f + ' ' + l + ' ' + month)).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = (new Date(f + ' ' + month + ' ' + l)).toString(); +reportCompare(expect, actual, 'f month l'); + +f = 2040; +l = 15; + +// year, month, day +expect = (new Date(f, 0, l)).toString(); + +actual = (new Date(month + ' ' + f + ' ' + l)).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = (new Date(f + ' ' + l + ' ' + month)).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = (new Date(f + ' ' + month + ' ' + l)).toString(); +reportCompare(expect, actual, 'f month l'); + diff --git a/js/src/tests/non262/Date/regress-309925-01.js b/js/src/tests/non262/Date/regress-309925-01.js new file mode 100644 index 0000000000..ee6daaffc4 --- /dev/null +++ b/js/src/tests/non262/Date/regress-309925-01.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 309925; +var summary = 'Correctly parse Date strings with HH:MM'; +var actual = new Date('Sep 24, 11:58 105') + ''; +var expect = new Date('Sep 24, 11:58:00 105') + ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Date/regress-309925-02.js b/js/src/tests/non262/Date/regress-309925-02.js new file mode 100644 index 0000000000..60bbfc33b0 --- /dev/null +++ b/js/src/tests/non262/Date/regress-309925-02.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 309925; +var summary = 'Correctly parse Date strings with HH:MM(comment)'; +var actual = new Date('Sep 24, 11:58(comment) 105') + ''; +var expect = new Date('Sep 24, 11:58:00 (comment) 105') + ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Date/regress-346027.js b/js/src/tests/non262/Date/regress-346027.js new file mode 100644 index 0000000000..ad1dc9e55f --- /dev/null +++ b/js/src/tests/non262/Date/regress-346027.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 346027; +var summary = 'Date.prototype.setFullYear()'; +var actual = ''; +var expect = true; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d = new Date(); + d.setFullYear(); + actual = isNaN(d.getFullYear()); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/regress-346363.js b/js/src/tests/non262/Date/regress-346363.js new file mode 100644 index 0000000000..6381899fbc --- /dev/null +++ b/js/src/tests/non262/Date/regress-346363.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 346363; +var summary = 'Date.prototype.setFullYear()'; +var actual = ''; +var expect = true; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d = new Date(); + d.setFullYear(); + d.setFullYear(2006); + actual = d.getFullYear() == 2006; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/regress-452786.js b/js/src/tests/non262/Date/regress-452786.js new file mode 100644 index 0000000000..c8943b1f99 --- /dev/null +++ b/js/src/tests/non262/Date/regress-452786.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 452786; +var summary = 'Do not crash with (new Date()).getMonth.call(new Function())'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + (new Date()).getMonth.call(new Function()); + } + catch(ex) + { + } + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js b/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js new file mode 100644 index 0000000000..56c9fc262c --- /dev/null +++ b/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +const testCases = [ + { + timeZone: "Europe/London", + string: "Tue Aug 14 2018 00:00:00 GMT+0100 (BST)", + alternativeTimeZones: ["British Summer Time"], + localeString: "8/14/2018, 12:00:00 AM GMT+1", + }, + { + timeZone: "UTC", + string: "Tue Aug 14 2018 00:00:00 GMT+0000 (UTC)", + alternativeTimeZones: ["Coordinated Universal Time"], + localeString: "8/14/2018, 12:00:00 AM UTC", + }, +]; + +// Repeat twice to test both transitions (Europe/London -> UTC and UTC -> Europe/London). +for (let i = 0; i < 2; ++i) { + for (let {timeZone, string, localeString, alternativeTimeZones} of testCases) { + setTimeZone(timeZone); + + let dt = new Date(2018, 8 - 1, 14); + assertDateTime(dt, string, ...alternativeTimeZones); + assertEq(dt.toLocaleString("en-US", {timeZoneName: "short"}), localeString); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js b/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js new file mode 100644 index 0000000000..7e67d03742 --- /dev/null +++ b/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js @@ -0,0 +1,147 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +print("Test for correct short-circuiting implementation of Date.set methods"); + +/************** + * BEGIN TEST * + **************/ +var global = 0; +var date; + +/* Test that methods don't short circuit argument evaluation. */ +date = new Date(0).setSeconds(NaN, {valueOf:function(){global = 3}}); +assertEq(global, 3); + +date = new Date(0).setUTCSeconds(NaN, {valueOf:function(){global = 4}}); +assertEq(global, 4); + +date = new Date(0).setMinutes(NaN, {valueOf:function(){global = 5}}); +assertEq(global, 5); + +date = new Date(0).setUTCMinutes(NaN, {valueOf:function(){global = 6}}); +assertEq(global, 6); + +date = new Date(0).setHours(NaN, {valueOf:function(){global = 7}}); +assertEq(global, 7); + +date = new Date(0).setUTCHours(NaN, {valueOf:function(){global = 8}}); +assertEq(global, 8); + +date = new Date(0).setMonth(NaN, {valueOf:function(){global = 11}}); +assertEq(global, 11); + +date = new Date(0).setUTCMonth(NaN, {valueOf:function(){global = 12}}); +assertEq(global, 12); + +date = new Date(0).setFullYear(NaN, {valueOf:function(){global = 13}}); +assertEq(global, 13); + +date = new Date(0).setUTCFullYear(NaN, {valueOf:function(){global = 14}}); +assertEq(global, 14); + + + +/* Test that argument evaluation is not short circuited if Date == NaN */ +date = new Date(NaN).setMilliseconds({valueOf:function(){global = 15}}); +assertEq(global, 15); + +date = new Date(NaN).setUTCMilliseconds({valueOf:function(){global = 16}}); +assertEq(global, 16); + +date = new Date(NaN).setSeconds({valueOf:function(){global = 17}}); +assertEq(global, 17); + +date = new Date(NaN).setUTCSeconds({valueOf:function(){global = 18}}); +assertEq(global, 18); + +date = new Date(NaN).setMinutes({valueOf:function(){global = 19}}); +assertEq(global, 19); + +date = new Date(NaN).setUTCMinutes({valueOf:function(){global = 20}}); +assertEq(global, 20); + +date = new Date(NaN).setHours({valueOf:function(){global = 21}}); +assertEq(global, 21); + +date = new Date(NaN).setUTCHours({valueOf:function(){global = 22}}); +assertEq(global, 22); + +date = new Date(NaN).setDate({valueOf:function(){global = 23}}); +assertEq(global, 23); + +date = new Date(NaN).setUTCDate({valueOf:function(){global = 24}}); +assertEq(global, 24); + +date = new Date(NaN).setMonth({valueOf:function(){global = 25}}); +assertEq(global, 25); + +date = new Date(NaN).setUTCMonth({valueOf:function(){global = 26}}); +assertEq(global, 26); + +date = new Date(NaN).setFullYear({valueOf:function(){global = 27}}); +assertEq(global, 27); + +date = new Date(NaN).setUTCFullYear({valueOf:function(){global = 28}}); +assertEq(global, 28); + + +/* Test the combination of the above two. */ +date = new Date(NaN).setSeconds(NaN, {valueOf:function(){global = 31}}); +assertEq(global, 31); + +date = new Date(NaN).setUTCSeconds(NaN, {valueOf:function(){global = 32}}); +assertEq(global, 32); + +date = new Date(NaN).setMinutes(NaN, {valueOf:function(){global = 33}}); +assertEq(global, 33); + +date = new Date(NaN).setUTCMinutes(NaN, {valueOf:function(){global = 34}}); +assertEq(global, 34); + +date = new Date(NaN).setHours(NaN, {valueOf:function(){global = 35}}); +assertEq(global, 35); + +date = new Date(NaN).setUTCHours(NaN, {valueOf:function(){global = 36}}); +assertEq(global, 36); + +date = new Date(NaN).setMonth(NaN, {valueOf:function(){global = 39}}); +assertEq(global, 39); + +date = new Date(NaN).setUTCMonth(NaN, {valueOf:function(){global = 40}}); +assertEq(global, 40); + +date = new Date(NaN).setFullYear(NaN, {valueOf:function(){global = 41}}); +assertEq(global, 41); + +date = new Date(NaN).setUTCFullYear(NaN, {valueOf:function(){global = 42}}); +assertEq(global, 42); + + +/*Test two methods evaluation*/ +var secondGlobal = 0; + +date = new Date(NaN).setFullYear({valueOf:function(){global = 43}}, {valueOf:function(){secondGlobal = 1}}); +assertEq(global, 43); +assertEq(secondGlobal, 1); + +date = new Date(0).setFullYear(NaN, {valueOf:function(){global = 44}}, {valueOf:function(){secondGlobal = 2}}); +assertEq(global, 44); +assertEq(secondGlobal, 2); + + +/* Test year methods*/ +date = new Date(0).setYear({valueOf:function(){global = 45}}); +assertEq(global, 45); + +date = new Date(NaN).setYear({valueOf:function(){global = 46}}); +assertEq(global, 46); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/shell.js b/js/src/tests/non262/Date/shell.js new file mode 100644 index 0000000000..9246c1eaaa --- /dev/null +++ b/js/src/tests/non262/Date/shell.js @@ -0,0 +1,311 @@ +/** + * Date functions used by tests in Date suite + */ +(function(global) { + const msPerDay = 1000 * 60 * 60 * 24; + const msPerHour = 1000 * 60 * 60; + global.msPerHour = msPerHour; + + // Offset of tester's time zone from UTC. + const TZ_DIFF = GetRawTimezoneOffset(); + global.TZ_ADJUST = TZ_DIFF * msPerHour; + + const UTC_01_JAN_1900 = -2208988800000; + const UTC_01_JAN_2000 = 946684800000; + const UTC_29_FEB_2000 = UTC_01_JAN_2000 + 31 * msPerDay + 28 * msPerDay; + const UTC_01_JAN_2005 = UTC_01_JAN_2000 + TimeInYear(2000) + TimeInYear(2001) + + TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004); + global.UTC_01_JAN_1900 = UTC_01_JAN_1900; + global.UTC_01_JAN_2000 = UTC_01_JAN_2000; + global.UTC_29_FEB_2000 = UTC_29_FEB_2000; + global.UTC_01_JAN_2005 = UTC_01_JAN_2005; + + /* + * Originally, the test suite used a hard-coded value TZ_DIFF = -8. + * But that was only valid for testers in the Pacific Standard Time Zone! + * We calculate the proper number dynamically for any tester. We just + * have to be careful not to use a date subject to Daylight Savings Time... + */ + function GetRawTimezoneOffset() { + let t1 = new Date(2000, 1, 1).getTimezoneOffset(); + let t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); + + // 1) Time zone without daylight saving time. + // 2) Northern hemisphere with daylight saving time. + if ((t1 - t2) >= 0) + return -t1 / 60; + + // 3) Southern hemisphere with daylight saving time. + return -t2 / 60; + } + + function DaysInYear(y) { + return y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 366 : 365; + } + + function TimeInYear(y) { + return DaysInYear(y) * msPerDay; + } + + function getDefaultTimeZone() { + var tz = getTimeZone(); + switch (tz) { + case "EST": + case "EDT": + return "EST5EDT"; + + case "CST": + case "CDT": + return "CST6CDT"; + + case "MST": + case "MDT": + return "MST7MDT"; + + case "PST": + case "PDT": + return "PST8PDT"; + + default: + // Other time zones abbrevations are not supported. + return tz; + } + } + + function getDefaultLocale() { + // If the default locale looks like a BCP-47 language tag, return it. + var locale = global.getDefaultLocale(); + if (locale.match(/^[a-z][a-z0-9\-]+$/i)) + return locale; + + // Otherwise use undefined to reset to the default locale. + return undefined; + } + + let defaultTimeZone = null; + let defaultLocale = null; + + // Run the given test in the requested time zone. + function inTimeZone(tzname, fn) { + if (defaultTimeZone === null) + defaultTimeZone = getDefaultTimeZone(); + + setTimeZone(tzname); + try { + fn(); + } finally { + setTimeZone(defaultTimeZone); + } + } + global.inTimeZone = inTimeZone; + + // Run the given test with the requested locale. + function withLocale(locale, fn) { + if (defaultLocale === null) + defaultLocale = getDefaultLocale(); + + setDefaultLocale(locale); + try { + fn(); + } finally { + setDefaultLocale(defaultLocale); + } + } + global.withLocale = withLocale; + + const Month = { + January: 0, + February: 1, + March: 2, + April: 3, + May: 4, + June: 5, + July: 6, + August: 7, + September: 8, + October: 9, + November: 10, + December: 11, + }; + global.Month = Month; + + const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|"); + const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|"); + const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`; + const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`; + const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`); + + function assertDateTime(date, expected, ...alternativeTimeZones) { + let actual = date.toString(); + assertEq(dateTimeRE.test(expected), true, `${expected}`); + assertEq(dateTimeRE.test(actual), true, `${actual}`); + + let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected); + let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual); + + assertEq(actualDateTime, expectedDateTime); + + // The time zone identifier is optional, so only compare its value if + // it's present in |actual| and |expected|. + if (expectedTimeZone !== undefined && actualTimeZone !== undefined) { + // Test against the alternative time zone identifiers if necessary. + if (actualTimeZone !== expectedTimeZone) { + for (let alternativeTimeZone of alternativeTimeZones) { + if (actualTimeZone === alternativeTimeZone) { + expectedTimeZone = alternativeTimeZone; + break; + } + } + } + assertEq(actualTimeZone, expectedTimeZone); + } + } + global.assertDateTime = assertDateTime; +})(this); + + +function runDSTOffsetCachingTestsFraction(part, parts) +{ + var BUGNUMBER = 563938; + var summary = 'Cache DST offsets to improve SunSpider score'; + + print(BUGNUMBER + ": " + summary); + + var MAX_UNIX_TIMET = 2145859200; // "2037-12-31T08:00:00.000Z" (PST8PDT based!) + var RANGE_EXPANSION_AMOUNT = 30 * 24 * 60 * 60; + + /** + * Computes the time zone offset in minutes at the given timestamp. + */ + function tzOffsetFromUnixTimestamp(timestamp) + { + var d = new Date(NaN); + d.setTime(timestamp); // local slot = NaN, UTC slot = timestamp + return d.getTimezoneOffset(); // get UTC, calculate local => diff in minutes + } + + /** + * Clear the DST offset cache, leaving it initialized to include a timestamp + * completely unlike the provided one (i.e. one very, very far away in time + * from it). Thus an immediately following lookup for the provided timestamp + * will cache-miss and compute a clean value. + */ + function clearDSTOffsetCache(undesiredTimestamp) + { + var opposite = (undesiredTimestamp + MAX_UNIX_TIMET / 2) % MAX_UNIX_TIMET; + + // Generic purge to known, but not necessarily desired, state + tzOffsetFromUnixTimestamp(0); + tzOffsetFromUnixTimestamp(MAX_UNIX_TIMET); + + // Purge to desired state. Cycle 2x in case opposite or undesiredTimestamp + // is close to 0 or MAX_UNIX_TIMET. + tzOffsetFromUnixTimestamp(opposite); + tzOffsetFromUnixTimestamp(undesiredTimestamp); + tzOffsetFromUnixTimestamp(opposite); + tzOffsetFromUnixTimestamp(undesiredTimestamp); + } + + function computeCanonicalTZOffset(timestamp) + { + clearDSTOffsetCache(timestamp); + return tzOffsetFromUnixTimestamp(timestamp); + } + + var TEST_TIMESTAMPS_SECONDS = + [ + // Special-ish timestamps + 0, + RANGE_EXPANSION_AMOUNT, + MAX_UNIX_TIMET, + ]; + + var ONE_DAY = 24 * 60 * 60; + var EIGHTY_THREE_HOURS = 83 * 60 * 60; + var NINETY_EIGHT_HOURS = 98 * 60 * 60; + function nextIncrement(i) + { + return i === EIGHTY_THREE_HOURS ? NINETY_EIGHT_HOURS : EIGHTY_THREE_HOURS; + } + + // Now add a long sequence of non-special timestamps, from a fixed range, that + // overlaps a DST change by "a bit" on each side. 67 days should be enough + // displacement that we can occasionally exercise the implementation's + // thirty-day expansion and the DST-offset-change logic. Use two different + // increments just to be safe and catch something a single increment might not. + var DST_CHANGE_DATE = 1268553600; // March 14, 2010 + for (var t = DST_CHANGE_DATE - 67 * ONE_DAY, + i = nextIncrement(NINETY_EIGHT_HOURS), + end = DST_CHANGE_DATE + 67 * ONE_DAY; + t < end; + i = nextIncrement(i), t += i) + { + TEST_TIMESTAMPS_SECONDS.push(t); + } + + var TEST_TIMESTAMPS = + TEST_TIMESTAMPS_SECONDS.map(function(v) { return v * 1000; }); + + /************** + * BEGIN TEST * + **************/ + + // Compute the correct time zone offsets for all timestamps to be tested. + var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset); + + // Intentionally and knowingly invoking every single logic path in the cache + // isn't easy for a human to get right (and know he's gotten it right), so + // let's do it the easy way: exhaustively try all possible four-date sequences + // selecting from our array of possible timestamps. + + var sz = TEST_TIMESTAMPS.length; + var start = Math.floor((part - 1) / parts * sz); + var end = Math.floor(part / parts * sz); + + print("Exhaustively testing timestamps " + + "[" + start + ", " + end + ") of " + sz + "..."); + + try + { + for (var i = start; i < end; i++) + { + print("Testing timestamp " + i + "..."); + + var t1 = TEST_TIMESTAMPS[i]; + for (var j = 0; j < sz; j++) + { + var t2 = TEST_TIMESTAMPS[j]; + for (var k = 0; k < sz; k++) + { + var t3 = TEST_TIMESTAMPS[k]; + for (var w = 0; w < sz; w++) + { + var t4 = TEST_TIMESTAMPS[w]; + + clearDSTOffsetCache(t1); + + var tzo1 = tzOffsetFromUnixTimestamp(t1); + var tzo2 = tzOffsetFromUnixTimestamp(t2); + var tzo3 = tzOffsetFromUnixTimestamp(t3); + var tzo4 = tzOffsetFromUnixTimestamp(t4); + + assertEq(tzo1, CORRECT_TZOFFSETS[i]); + assertEq(tzo2, CORRECT_TZOFFSETS[j]); + assertEq(tzo3, CORRECT_TZOFFSETS[k]); + assertEq(tzo4, CORRECT_TZOFFSETS[w]); + } + } + } + } + } + catch (e) + { + assertEq(true, false, + "Error when testing with timestamps " + + i + ", " + j + ", " + k + ", " + w + + " (" + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ")!"); + } + + reportCompare(true, true); + print("All tests passed!"); +} diff --git a/js/src/tests/non262/Date/time-components-negative-zero.js b/js/src/tests/non262/Date/time-components-negative-zero.js new file mode 100644 index 0000000000..511dcc9fe4 --- /dev/null +++ b/js/src/tests/non262/Date/time-components-negative-zero.js @@ -0,0 +1,18 @@ +// Don't return negative zero for get[Hours,Minutes,Seconds,Milliseconds] for dates before 1970. + +let date = new Date(1955, 0, 1); +assertEq(date.getTime() < 0, true); +assertEq(date.getHours(), +0); +assertEq(date.getMinutes(), +0); +assertEq(date.getSeconds(), +0); +assertEq(date.getMilliseconds(), +0); + +let utc = new Date(Date.UTC(1955, 0, 1)); +assertEq(utc.getTime() < 0, true); +assertEq(utc.getUTCHours(), +0); +assertEq(utc.getUTCMinutes(), +0); +assertEq(utc.getUTCSeconds(), +0); +assertEq(utc.getUTCMilliseconds(), +0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-2038-pst.js b/js/src/tests/non262/Date/time-zone-2038-pst.js new file mode 100644 index 0000000000..2abad4dbfd --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-2038-pst.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +// U.S. daylight saving rules changed in 2007, excerpt from tzdata's +// northamerica file: +// NAME FROM TO IN ON AT SAVE LETTER/S +// US 1967 2006 Oct lastSun 2:00 0 S +// US 1967 1973 Apr lastSun 2:00 1:00 D +// US 1974 only Jan 6 2:00 1:00 D +// US 1975 only Feb 23 2:00 1:00 D +// US 1976 1986 Apr lastSun 2:00 1:00 D +// US 1987 2006 Apr Sun>=1 2:00 1:00 D +// US 2007 max Mar Sun>=8 2:00 1:00 D +// US 2007 max Nov Sun>=1 2:00 0 S + + +// When 2040 is mapped to 1984, the old U.S. rules are applied, i.e. DST isn't +// yet observed on March 31. If mapped to 2012, the new U.S. rules are applied +// and DST is already observed, which is the expected behaviour. +// A similar effect is visible in November. +// NOTE: This test expects that 2012 and 2040 use the same DST rules. If this +// ever changes, the test needs to be updated accordingly. +{ + let dt1 = new Date(2040, Month.March, 31); + assertDateTime(dt1, "Sat Mar 31 2040 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2040, Month.November, 1); + assertDateTime(dt2, "Thu Nov 01 2040 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +} + +// 2038 is mapped to 2027 instead of 1971. +{ + let dt1 = new Date(2038, Month.March, 31); + assertDateTime(dt1, "Wed Mar 31 2038 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2038, Month.November, 1); + assertDateTime(dt2, "Mon Nov 01 2038 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-etc_localetime.js b/js/src/tests/non262/Date/time-zone-etc_localetime.js new file mode 100644 index 0000000000..eaf8f7d940 --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-etc_localetime.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +function timeZoneName() { + var dtf = new Intl.DateTimeFormat("en-US", {timeZoneName: "long"}); + return dtf.formatToParts().filter(x => x.type === "timeZoneName")[0].value; +} + +// Calling setTimeZone() with an undefined argument clears the TZ environment +// variable and by that reveal the actual system time zone. +setTimeZone(undefined); +var systemTimeZone = getTimeZone(); +var systemTimeZoneName = timeZoneName(); + +// Set to an unlikely system time zone, so that the next call to setTimeZone() +// will lead to a time zone change. +setTimeZone("Antarctica/Troll"); + +// Now call with the file path ":/etc/localtime" which is special-cased in +// DateTimeInfo to read the system time zone. +setTimeZone(":/etc/localtime"); + +assertEq(getTimeZone(), systemTimeZone); +assertEq(timeZoneName(), systemTimeZoneName); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-path.js b/js/src/tests/non262/Date/time-zone-path.js new file mode 100644 index 0000000000..3422022e2b --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-path.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +function timeZoneName() { + var dtf = new Intl.DateTimeFormat("en-US", {timeZoneName: "long"}); + return dtf.formatToParts(Date.UTC(2017, 2, 31, 12, 0, 0)).filter(x => x.type === "timeZoneName")[0].value; +} + +setTimeZone("Europe/Paris"); +assertEq(timeZoneName(), "Central European Summer Time"); + +setTimeZone(":Europe/Helsinki"); +assertEq(timeZoneName(), "Eastern European Summer Time"); + +setTimeZone("::Europe/London"); // two colons, invalid +assertEq(timeZoneName(), "Coordinated Universal Time"); + +setTimeZone("/this-part-is-ignored/zoneinfo/America/Chicago"); +assertEq(timeZoneName(), "Central Daylight Time"); + +setTimeZone(":/this-part-is-ignored/zoneinfo/America/Phoenix"); +assertEq(timeZoneName(), "Mountain Standard Time"); + +setTimeZone("::/this-part-is-ignored/zoneinfo/America/Los_Angeles"); // two colons, invalid +assertEq(timeZoneName(), "Coordinated Universal Time"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-pst.js b/js/src/tests/non262/Date/time-zone-pst.js new file mode 100644 index 0000000000..341d3c8236 --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-pst.js @@ -0,0 +1,120 @@ +// |reftest| skip-if(!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +const msPerMinute = 60 * 1000; + +function shortTimeZone(str) { + return str.replace("(Pacific Standard Time)", "(PST)") + .replace("(Pacific Daylight Time)", "(PDT)"); +} + +function assertEqDate(dt, date, time) { + assertEq(shortTimeZone(dt.toString()), `${date} ${time}`); + assertEq(dt.toDateString(), date); + assertEq(shortTimeZone(dt.toTimeString()), time); +} + +// PDT -> PST, using milliseconds from epoch. +{ + let midnight = new Date(2016, Month.November, 6, 0, 0, 0, 0); + let midnightUTC = Date.UTC(2016, Month.November, 6, 0, 0, 0, 0); + + // Ensure midnight time is correct. + assertEq(midnightUTC - midnight.getTime(), -7 * msPerHour); + + let tests = [ + { offset: 0 * 60, date: "Sun Nov 06 2016", time: "00:00:00 GMT-0700 (PDT)" }, + { offset: 0 * 60 + 30, date: "Sun Nov 06 2016", time: "00:30:00 GMT-0700 (PDT)" }, + { offset: 1 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0700 (PDT)" }, + { offset: 1 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0700 (PDT)" }, + { offset: 2 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 2 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 3 * 60, date: "Sun Nov 06 2016", time: "02:00:00 GMT-0800 (PST)" }, + { offset: 3 * 60 + 30, date: "Sun Nov 06 2016", time: "02:30:00 GMT-0800 (PST)" }, + { offset: 4 * 60, date: "Sun Nov 06 2016", time: "03:00:00 GMT-0800 (PST)" }, + { offset: 4 * 60 + 30, date: "Sun Nov 06 2016", time: "03:30:00 GMT-0800 (PST)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(midnight.getTime() + offset * msPerMinute); + assertEqDate(dt, date, time); + } +} + + +// PDT -> PST, using local date-time. +{ + let tests = [ + { offset: 0 * 60, date: "Sun Nov 06 2016", time: "00:00:00 GMT-0700 (PDT)" }, + { offset: 0 * 60 + 30, date: "Sun Nov 06 2016", time: "00:30:00 GMT-0700 (PDT)" }, + { offset: 1 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0700 (PDT)" }, + { offset: 1 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0700 (PDT)" }, + { offset: 2 * 60, date: "Sun Nov 06 2016", time: "02:00:00 GMT-0800 (PST)" }, + { offset: 2 * 60 + 30, date: "Sun Nov 06 2016", time: "02:30:00 GMT-0800 (PST)" }, + { offset: 3 * 60, date: "Sun Nov 06 2016", time: "03:00:00 GMT-0800 (PST)" }, + { offset: 3 * 60 + 30, date: "Sun Nov 06 2016", time: "03:30:00 GMT-0800 (PST)" }, + { offset: 4 * 60, date: "Sun Nov 06 2016", time: "04:00:00 GMT-0800 (PST)" }, + { offset: 4 * 60 + 30, date: "Sun Nov 06 2016", time: "04:30:00 GMT-0800 (PST)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(2016, Month.November, 6, (offset / 60)|0, (offset % 60), 0, 0); + assertEqDate(dt, date, time); + } +} + + +// PST -> PDT, using milliseconds from epoch. +{ + let midnight = new Date(2016, Month.March, 13, 0, 0, 0, 0); + let midnightUTC = Date.UTC(2016, Month.March, 13, 0, 0, 0, 0); + + // Ensure midnight time is correct. + assertEq(midnightUTC - midnight.getTime(), -8 * msPerHour); + + let tests = [ + { offset: 0 * 60, date: "Sun Mar 13 2016", time: "00:00:00 GMT-0800 (PST)" }, + { offset: 0 * 60 + 30, date: "Sun Mar 13 2016", time: "00:30:00 GMT-0800 (PST)" }, + { offset: 1 * 60, date: "Sun Mar 13 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 1 * 60 + 30, date: "Sun Mar 13 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 2 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 2 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 3 * 60, date: "Sun Mar 13 2016", time: "04:00:00 GMT-0700 (PDT)" }, + { offset: 3 * 60 + 30, date: "Sun Mar 13 2016", time: "04:30:00 GMT-0700 (PDT)" }, + { offset: 4 * 60, date: "Sun Mar 13 2016", time: "05:00:00 GMT-0700 (PDT)" }, + { offset: 4 * 60 + 30, date: "Sun Mar 13 2016", time: "05:30:00 GMT-0700 (PDT)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(midnight.getTime() + offset * msPerMinute); + assertEqDate(dt, date, time); + } +} + + +// PST -> PDT, using local date-time. +{ + let tests = [ + { offset: 0 * 60, date: "Sun Mar 13 2016", time: "00:00:00 GMT-0800 (PST)" }, + { offset: 0 * 60 + 30, date: "Sun Mar 13 2016", time: "00:30:00 GMT-0800 (PST)" }, + { offset: 1 * 60, date: "Sun Mar 13 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 1 * 60 + 30, date: "Sun Mar 13 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 2 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 2 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 3 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 3 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 4 * 60, date: "Sun Mar 13 2016", time: "04:00:00 GMT-0700 (PDT)" }, + { offset: 4 * 60 + 30, date: "Sun Mar 13 2016", time: "04:30:00 GMT-0700 (PDT)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(2016, Month.March, 13, (offset / 60)|0, (offset % 60), 0, 0); + assertEqDate(dt, date, time); + } +} + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-historic.js b/js/src/tests/non262/Date/time-zones-historic.js new file mode 100644 index 0000000000..3117870687 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-historic.js @@ -0,0 +1,538 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// bug 487897 +inTimeZone("Europe/London", () => { + let dt1 = new Date(1970, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt1, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); + assertEq(dt1.getHours(), 0); + + let dt2 = new Date(1915, Month.January, 1); + assertDateTime(dt2, "Fri Jan 01 1915 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt3 = new Date(1970, Month.January, 1); + assertDateTime(dt3, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); +}); + +// bug 637244 +inTimeZone("Asia/Novosibirsk", () => { + let dt1 = new Date("1942-03-01T00:00:00"); + assertDateTime(dt1, "Sun Mar 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + dt1.setMonth(Month.April); + assertDateTime(dt1, "Wed Apr 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + let dt2 = new Date(2010, Month.October, 31); + assertDateTime(dt2, "Sun Oct 31 2010 00:00:00 GMT+0700 (Novosibirsk Summer Time)"); + dt2.setMonth(Month.November); + assertDateTime(dt2, "Wed Dec 01 2010 00:00:00 GMT+0600 (Novosibirsk Standard Time)"); + + let dt3 = new Date(1942, Month.April, 1); + assertDateTime(dt3, "Wed Apr 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + function getNumberOfDaysInMonth(year, month) { + switch (month) { + case Month.January: + case Month.March: + case Month.May: + case Month.July: + case Month.August: + case Month.October: + case Month.December: + return 31; + case Month.April: + case Month.June: + case Month.September: + case Month.November: + return 30; + case Month.February: + if (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) + return 29; + return 28; + } + throw new Error(`Illegal month value: ${month}`); + } + + for (let year = 1900; year <= 2142; ++year) { + for (let month = Month.January; month <= Month.December; ++month) { + const numDays = getNumberOfDaysInMonth(year, month); + for (let day = 1; day <= numDays; ++day) { + let date = new Date(year, month, day); + assertEq(date.getMonth(), month); + } + } + } + + let dt4 = new Date(1984, Month.April, 1); + assertDateTime(dt4, "Sun Apr 01 1984 01:00:00 GMT+0800 (Novosibirsk Summer Time)"); + + let dt5 = new Date(1984, Month.March, 1); + assertDateTime(dt5, "Thu Mar 01 1984 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + let dt6 = new Date(1984, Month.April, 1); + assertEq(dt6.toUTCString(), "Sat, 31 Mar 1984 17:00:00 GMT"); + assertEq(dt6.getTime(), 449600400000); +}); +inTimeZone("Europe/Tallinn", () => { + let dt = new Date(2040, Month.March, 31, 20); + + for (let {datetime, date, hours} of [ + {datetime: "Sat Mar 31 2040 20:00:00", date: 31, hours: 20}, + {datetime: "Sat Mar 31 2040 22:00:00", date: 31, hours: 22}, + {datetime: "Sun Apr 01 2040 00:00:00", date: 1, hours: 0}, + {datetime: "Sun Apr 01 2040 02:00:00", date: 1, hours: 2}, + {datetime: "Sun Apr 01 2040 04:00:00", date: 1, hours: 4}, + {datetime: "Sun Apr 01 2040 06:00:00", date: 1, hours: 6}, + {datetime: "Sun Apr 01 2040 08:00:00", date: 1, hours: 8}, + ]) { + assertDateTime(dt, `${datetime} GMT+0300 (Eastern European Summer Time)`); + assertEq(dt.getDate(), date); + assertEq(dt.getHours(), hours); + assertEq(dt.getTimezoneOffset(), -180); + + dt.setHours(dt.getHours() + 2); + } +}); +inTimeZone("Europe/Riga", () => { + let dt1 = new Date(2016, Month.March, 27, 2, 59); + assertDateTime(dt1, "Sun Mar 27 2016 02:59:00 GMT+0200 (Eastern European Standard Time)"); + + let dt2 = new Date(2016, Month.March, 27, 3, 0); + assertDateTime(dt2, "Sun Mar 27 2016 04:00:00 GMT+0300 (Eastern European Summer Time)"); +}); + +// bug 704486 +inTimeZone("Europe/Zagreb", () => { + let dt = new Date(Date.UTC(1942, Month.June, 11, 22, 0, 0, 0)); + assertDateTime(dt, "Fri Jun 12 1942 00:00:00 GMT+0200 (Central European Summer Time)"); + assertEq(dt.getFullYear(), 1942); + assertEq(dt.getMonth(), Month.June); + assertEq(dt.getDate(), 12); + assertEq(dt.getHours(), 0); + assertEq(dt.getMinutes(), 0); + assertEq(dt.getSeconds(), 0); + assertEq(dt.getMilliseconds(), 0); + assertEq(dt.getTimezoneOffset(), -120); +}); + +// bug 935909 +inTimeZone("Europe/London", () => { + let dt1 = new Date(1954, Month.January, 1); + assertDateTime(dt1, "Fri Jan 01 1954 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt2 = new Date(1965, Month.January, 1); + assertDateTime(dt2, "Fri Jan 01 1965 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt3 = new Date(1970, Month.January, 1); + assertDateTime(dt3, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); + + let dt4 = new Date(-504921600000); + assertDateTime(dt4, "Fri Jan 01 1954 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt5 = new Date(1974, Month.January, 1); + assertDateTime(dt5, "Tue Jan 01 1974 00:00:00 GMT+0000 (Greenwich Mean Time)"); +}); +inTimeZone("Europe/Dublin", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + dt.setFullYear(1970); + assertEq(dt.getFullYear(), 1970); +}); + +// bug 937261 +inTimeZone("Europe/Lisbon", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt, "Mon Jan 01 1900 00:00:00 GMT-0036 (Western European Standard Time)"); + + dt.setFullYear(2015); + assertDateTime(dt, "Thu Jan 01 2015 00:00:00 GMT+0000 (Western European Standard Time)"); + + dt.setMonth(Month.November); + assertDateTime(dt, "Sun Nov 01 2015 00:00:00 GMT+0000 (Western European Standard Time)"); +}); +inTimeZone("Europe/London", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt, "Mon Jan 01 1900 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + dt.setFullYear(2015); + assertDateTime(dt, "Thu Jan 01 2015 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + dt.setMonth(Month.November); + assertDateTime(dt, "Sun Nov 01 2015 00:00:00 GMT+0000 (Greenwich Mean Time)"); +}); + +// bug 1079720 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT+0400 (Moscow Standard Time)"); + assertEq(dt1.toISOString(), "2013-12-31T20:00:00.000Z"); + assertEq(dt1.getHours(), 0); + + let dt2 = new Date(2013, Month.January, 1); + assertDateTime(dt2, "Tue Jan 01 2013 00:00:00 GMT+0400 (Moscow Standard Time)"); + + let dt3 = new Date(new Date(2014, Month.December, 1).setMonth(Month.January)); + assertDateTime(dt3, "Wed Jan 01 2014 00:00:00 GMT+0400 (Moscow Standard Time)"); + assertEq(dt3.getFullYear(), 2014); + + let dt4 = new Date(2040, Month.April, 1); + assertDateTime(dt4, "Sun Apr 01 2040 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt5 = new Date(2043, Month.April, 1); + assertDateTime(dt5, "Wed Apr 01 2043 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt6 = new Date(2054, Month.April, 1); + assertDateTime(dt6, "Wed Apr 01 2054 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt7 = new Date(2065, Month.April, 1); + assertDateTime(dt7, "Wed Apr 01 2065 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt8 = new Date(2068, Month.April, 1); + assertDateTime(dt8, "Sun Apr 01 2068 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt9 = new Date(2071, Month.April, 1); + assertDateTime(dt9, "Wed Apr 01 2071 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt10 = new Date(2082, Month.April, 1); + assertDateTime(dt10, "Wed Apr 01 2082 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt11 = new Date(2093, Month.April, 1); + assertDateTime(dt11, "Wed Apr 01 2093 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt12 = new Date(2096, Month.April, 1); + assertDateTime(dt12, "Sun Apr 01 2096 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt13 = new Date(2099, Month.April, 1); + assertDateTime(dt13, "Wed Apr 01 2099 00:00:00 GMT+0300 (Moscow Standard Time)"); +}); + +// bug 1107837 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(2015, Month.January, 4); + assertDateTime(dt1, "Sun Jan 04 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt2 = new Date(2015, Month.January, 5); + assertDateTime(dt2, "Mon Jan 05 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt3 = new Date(2015, Month.January, 6); + assertDateTime(dt3, "Tue Jan 06 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt4 = new Date(2015, Month.January, 7); + assertDateTime(dt4, "Wed Jan 07 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt5 = new Date(2015, Month.January, 8); + assertDateTime(dt5, "Thu Jan 08 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt6 = new Date(2015, Month.January, 9); + assertDateTime(dt6, "Fri Jan 09 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); +}); + +// bug 1122571 +inTimeZone("Europe/Berlin", () => { + const locale = "en-001"; + const opts = {timeZoneName: "long", hour12: false}; + + let dt1 = new Date(1950, Month.March, 28); + assertDateTime(dt1, "Tue Mar 28 1950 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt1.toLocaleString(locale, opts), "28/03/1950, 00:00:00 GMT+01:00"); + + let dt2 = new Date(1950, Month.July, 1); + assertDateTime(dt2, "Sat Jul 01 1950 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt2.toLocaleString(locale, opts), "01/07/1950, 00:00:00 GMT+01:00"); + + let dt3 = new Date(1960, Month.March, 27); + assertDateTime(dt3, "Sun Mar 27 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt3.toLocaleString(locale, opts), "27/03/1960, 00:00:00 GMT+01:00"); + + let dt4 = new Date(1960, Month.March, 28); + assertDateTime(dt4, "Mon Mar 28 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt4.toLocaleString(locale, opts), "28/03/1960, 00:00:00 GMT+01:00"); + + let dt5 = new Date(1960, Month.March, 29); + assertDateTime(dt5, "Tue Mar 29 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt5.toLocaleString(locale, opts), "29/03/1960, 00:00:00 GMT+01:00"); + + let dt6 = new Date(1960, Month.July, 1); + assertDateTime(dt6, "Fri Jul 01 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt6.toLocaleString(locale, opts), "01/07/1960, 00:00:00 GMT+01:00"); + + let dt7 = new Date(1961, Month.July, 1); + assertDateTime(dt7, "Sat Jul 01 1961 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt7.toLocaleString(locale, opts), "01/07/1961, 00:00:00 GMT+01:00"); + + let dt8 = new Date(1970, Month.March, 1); + assertDateTime(dt8, "Sun Mar 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt8.toLocaleString(locale, opts), "01/03/1970, 00:00:00 Central European Standard Time"); + + let dt9 = new Date(1970, Month.March, 27); + assertDateTime(dt9, "Fri Mar 27 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt9.toLocaleString(locale, opts), "27/03/1970, 00:00:00 Central European Standard Time"); + + let dt10 = new Date(1970, Month.March, 28); + assertDateTime(dt10, "Sat Mar 28 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt10.toLocaleString(locale, opts), "28/03/1970, 00:00:00 Central European Standard Time"); + + let dt11 = new Date(1970, Month.July, 1); + assertDateTime(dt11, "Wed Jul 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt11.toLocaleString(locale, opts), "01/07/1970, 00:00:00 Central European Standard Time"); +}); + +// bug 1143398 +inTimeZone("Australia/Adelaide", () => { + let dt = new Date(621000); + assertDateTime(dt, "Thu Jan 01 1970 09:40:21 GMT+0930 (Australian Central Standard Time)"); + assertEq(dt.getUTCFullYear(), 1970); + + dt.setMilliseconds(dt.getMilliseconds()); + dt.setSeconds(dt.getSeconds()); + + assertDateTime(dt, "Thu Jan 01 1970 09:40:21 GMT+0930 (Australian Central Standard Time)"); + assertEq(dt.getUTCFullYear(), 1970); +}); +inTimeZone("America/Denver", () => { + let dt = new Date(1446361200000); + assertDateTime(dt, "Sun Nov 01 2015 01:00:00 GMT-0600 (Mountain Daylight Time)"); + + assertEq(dt.getTime(), 1446361200000); + dt.setMilliseconds(0); + assertEq(dt.getTime(), 1446361200000); +}); + +// bug 1233809 +inTimeZone("America/New_York", () => { + let dt = new Date(1980, Month.March, 10); + assertDateTime(dt, "Mon Mar 10 1980 00:00:00 GMT-0500 (Eastern Standard Time)"); +}); + +// bug 1254041 +inTimeZone("Asia/Ho_Chi_Minh", () => { + let dt1 = new Date(Date.UTC(1969, Month.December, 31, 23, 0)); + assertDateTime(dt1, "Thu Jan 01 1970 07:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), -3600000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 07:30:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), -1800000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 08:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 0); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 08:30:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 1800000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 09:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 3600000); + + let dt2 = new Date(-1); + assertEq(dt2.getTime(), -1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 0); + + dt2.setTime(1); + assertEq(dt2.getTime(), 1); + + dt2.setMilliseconds(dt2.getMilliseconds() - 1); + assertEq(dt2.getTime(), 0); + + dt2.setMilliseconds(dt2.getMilliseconds() - 1); + assertEq(dt2.getTime(), -1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 0); + + dt2.setMilliseconds(dt2.getMilliseconds() + 3600000); + assertEq(dt2.getTime(), 3600000); + + dt2.setMilliseconds(dt2.getMilliseconds() + (3600000 * 2 - 1)); + assertEq(dt2.getTime(), 3600000 * 3 - 1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 3600000 * 3); + + dt2.setMilliseconds(dt2.getMilliseconds() + (3600000 * 2)); + assertEq(dt2.getTime(), 3600000 * 5); + + let dt3 = new Date(0); + assertDateTime(dt3, "Thu Jan 01 1970 08:00:00 GMT+0800 (Indochina Time)"); + + let dt4 = new Date(-1); + assertDateTime(dt4, "Thu Jan 01 1970 07:59:59 GMT+0800 (Indochina Time)"); +}); + +// bug 1300197 +inTimeZone("Europe/Dublin", () => { + let dt = new Date(1910, Month.January, 1); + assertDateTime(dt, "Sat Jan 01 1910 00:00:00 GMT-0025 (Greenwich Mean Time)"); +}); + +// bug 1304774 +inTimeZone("Europe/Zurich", () => { + let dt = new Date(1986, Month.April, 4, 0, 0, 0, 0); + assertDateTime(dt, "Fri Apr 04 1986 00:00:00 GMT+0200 (Central European Summer Time)"); + assertEq(dt.getTimezoneOffset(), -120); +}); + +// bug 1330307 +inTimeZone("Europe/Moscow", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0400 (Moscow Standard Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); +inTimeZone("Asia/Baku", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0500 (Azerbaijan Summer Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); +inTimeZone("Asia/Tbilisi", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0400 (Georgia Standard Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); + +// bug 1335818 +inTimeZone("Asia/Jerusalem", () => { + let dt1 = new Date(2013, Month.March, 22, 1, 0, 0, 0); + assertDateTime(dt1, "Fri Mar 22 2013 01:00:00 GMT+0200 (Israel Standard Time)"); + + let dt2 = new Date(2013, Month.March, 22, 2, 0, 0, 0); + assertDateTime(dt2, "Fri Mar 22 2013 02:00:00 GMT+0200 (Israel Standard Time)"); + + let dt3 = new Date(2013, Month.March, 22, 3, 0, 0, 0); + assertDateTime(dt3, "Fri Mar 22 2013 03:00:00 GMT+0200 (Israel Standard Time)"); + + let dt4 = new Date(2013, Month.March, 29, 1, 0, 0, 0); + assertDateTime(dt4, "Fri Mar 29 2013 01:00:00 GMT+0200 (Israel Standard Time)"); + + let dt5 = new Date(2013, Month.March, 29, 2, 0, 0, 0); + assertDateTime(dt5, "Fri Mar 29 2013 03:00:00 GMT+0300 (Israel Daylight Time)"); + + let dt6 = new Date(2013, Month.March, 29, 3, 0, 0, 0); + assertDateTime(dt6, "Fri Mar 29 2013 03:00:00 GMT+0300 (Israel Daylight Time)"); +}); + +// bug 1342853 +inTimeZone("America/Sao_Paulo", () => { + let dt1 = new Date(2017, Month.October, 14, 12, 0, 0); + assertDateTime(dt1, "Sat Oct 14 2017 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt1.getTimezoneOffset(), 180); + + let dt2 = new Date(2017, Month.October, 15, 12, 0, 0); + assertDateTime(dt2, "Sun Oct 15 2017 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt2.getTimezoneOffset(), 120); + + let dt3 = new Date(2018, Month.February, 17, 12, 0, 0); + assertDateTime(dt3, "Sat Feb 17 2018 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt3.getTimezoneOffset(), 120); + + let dt4 = new Date(2018, Month.February, 18, 12, 0, 0); + assertDateTime(dt4, "Sun Feb 18 2018 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt4.getTimezoneOffset(), 180); + + let dt5 = new Date(2018, Month.November, 3, 12, 0, 0); + assertDateTime(dt5, "Sat Nov 03 2018 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt5.getTimezoneOffset(), 180); + + let dt6 = new Date(2018, Month.November, 4, 12, 0, 0); + assertDateTime(dt6, "Sun Nov 04 2018 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt6.getTimezoneOffset(), 120); + + let dt7 = new Date(2019, Month.February, 16, 12, 0, 0); + assertDateTime(dt7, "Sat Feb 16 2019 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt7.getTimezoneOffset(), 120); + + let dt8 = new Date(2019, Month.February, 17, 12, 0, 0); + assertDateTime(dt8, "Sun Feb 17 2019 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt8.getTimezoneOffset(), 180); +}); + +// bug 1365192 +inTimeZone("America/Asuncion", () => { + let dt = new Date(2018, Month.March, 31); + assertDateTime(dt, "Sat Mar 31 2018 00:00:00 GMT-0400 (Paraguay Standard Time)"); + assertEq(dt.getTimezoneOffset(), 240); +}); + +// bug 1385643 +inTimeZone("Europe/Warsaw", () => { + let shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + let dtf = new Intl.DateTimeFormat("en-US", {month: "short"}); + + for (let year = 1900; year <= 2100; ++year) { + for (let month = Month.January; month <= Month.December; ++month) { + let date = new Date(year, month, 1); + assertEq(dtf.format(date), shortMonths[month]); + } + } +}); + +// bug 1401696 +inTimeZone("Europe/Berlin", () => { + let dt = new Date(1970, Month.January, 1, 0, 0, 0); + assertDateTime(dt, "Thu Jan 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); +}); + +// bug 1459842 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(1004, Month.April, 1, 2, 0, 0); + assertDateTime(dt1, "Sun Apr 01 1004 02:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt1.getHours(), 2); + + let dt2 = new Date(1004, Month.April, 1, 1, 0, 0); + assertDateTime(dt2, "Sun Apr 01 1004 01:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt2.getHours(), 1); + + let dt3 = new Date(1004, Month.April, 1, 0, 0, 0); + assertDateTime(dt3, "Sun Apr 01 1004 00:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt3.getHours(), 0); + + let dt4 = new Date(1004, Month.March, 1, 2, 0, 0); + assertDateTime(dt4, "Thu Mar 01 1004 02:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt4.getHours(), 2); + + let dt5 = new Date(1004, Month.March, 1, 1, 0, 0); + assertDateTime(dt5, "Thu Mar 01 1004 01:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt5.getHours(), 1); + + let dt6 = new Date(1004, Month.March, 1, 0, 0, 0); + assertDateTime(dt6, "Thu Mar 01 1004 00:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt6.getHours(), 0); + +}); + +// bug 1799638 +inTimeZone("Asia/Tokyo", () => { + let dt1 = new Date(1948, Month.May, 1, 23, 59, 59); + assertDateTime(dt1, "Sat May 01 1948 23:59:59 GMT+0900 (Japan Standard Time)"); + assertEq(dt1.getTimezoneOffset(), -540); + + let dt2 = new Date(1948, Month.May, 1, 24, 0, 0); + assertDateTime(dt2, "Sun May 02 1948 01:00:00 GMT+1000 (Japan Daylight Time)"); + assertEq(dt2.getTimezoneOffset(), -600); + + let dt3 = new Date(1948, Month.May, 1, 23, 59, 59, 1); + assertDateTime(dt3, "Sat May 01 1948 23:59:59 GMT+0900 (Japan Standard Time)"); + assertEq(dt3.getTimezoneOffset(), -540); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(1966, Month.April, 24, 1, 59, 59); + assertDateTime(dt1, "Sun Apr 24 1966 01:59:59 GMT-0500 (Eastern Standard Time)"); + assertEq(dt1.getTimezoneOffset(), 300); + + let dt2 = new Date(1966, Month.April, 24, 2, 0, 0); + assertDateTime(dt2, "Sun Apr 24 1966 03:00:00 GMT-0400 (Eastern Daylight Time)"); + assertEq(dt2.getTimezoneOffset(), 240); + + let dt3 = new Date(1966, Month.April, 24, 1, 59, 59, 1); + assertDateTime(dt3, "Sun Apr 24 1966 01:59:59 GMT-0500 (Eastern Standard Time)"); + assertEq(dt3.getTimezoneOffset(), 300); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-imported.js b/js/src/tests/non262/Date/time-zones-imported.js new file mode 100644 index 0000000000..8a13e34981 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-imported.js @@ -0,0 +1,1020 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// Imported tests from es6draft and then adapted to use ICU/CLDR time zone display names. + +function assertSame(expected, actual, message = undefined) { + if (message !== undefined) + assertEq(actual, expected, String(message)); + else + assertEq(actual, expected); +} + +function assertTrue(actual, message = undefined) { + assertSame(true, actual, message); +} + +// File: lib/datetime.jsm +const { + DayOfWeek, + Month, + DateTime, + TimeZone, + Format, +} = (function() { + +// 5.2 Algorithm Conventions +function modulo(dividend, divisor) { + assertTrue(typeof dividend === "number"); + assertTrue(typeof divisor === "number"); + assertTrue(divisor !== 0 && Number.isFinite(divisor)); + let remainder = dividend % divisor; + // NB: add +0 to convert -0 to +0 + return (remainder >= 0 ? remainder + 0 : remainder + divisor); +} + +// 7.1.4 ToInteger ( argument ) +function ToInteger(number) { + /* steps 1-2 */ + assertTrue(typeof number === "number"); + /* step 3 */ + if (Number.isNaN(number)) + return +0.0; + /* step 4 */ + if (number == 0.0 || !Number.isFinite(number)) + return number; + /* step 5 */ + return Math.sign(number) * Math.floor(Math.abs(number)); +} + +// 20.3.1.2 Day Number and Time within Day +const msPerDay = 86400000; + +// 20.3.1.2 Day Number and Time within Day +function Day(t) { + assertTrue(typeof t === "number"); + return Math.floor(t / msPerDay); +} + +// 20.3.1.2 Day Number and Time within Day +function TimeWithinDay(t) { + assertTrue(typeof t === "number"); + return modulo(t, msPerDay); +} + +// 20.3.1.3 Year Number +function DaysInYear(y) { + assertTrue(typeof y === "number"); + if (y % 4 !== 0) { + return 365; + } + if (y % 100 !== 0) { + return 366; + } + if (y % 400 !== 0) { + return 365; + } + return 366; +} + +// 20.3.1.3 Year Number +function DayFromYear(y) { + assertTrue(typeof y === "number"); + return 365 * (y - 1970) + Math.floor((y - 1969) / 4) - Math.floor((y - 1901) / 100) + Math.floor((y - 1601) / 400); +} + +// 20.3.1.3 Year Number +function TimeFromYear(y) { + assertTrue(typeof y === "number"); + return msPerDay * DayFromYear(y); +} + +// TODO: fill in rest + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +const HoursPerDay = 24; +const MinutesPerHour = 60; +const SecondsPerMinute = 60; +const msPerSecond = 1000; +const msPerMinute = msPerSecond * SecondsPerMinute; +const msPerHour = msPerMinute * MinutesPerHour; + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function HourFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerHour), HoursPerDay); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function MinFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerMinute), MinutesPerHour); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function SecFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerSecond), SecondsPerMinute); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function msFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(t, msPerSecond); +} + +// 20.3.1.11 MakeTime (hour, min, sec, ms) +function MakeTime(hour, min, sec, ms) { + assertTrue(typeof hour === "number"); + assertTrue(typeof min === "number"); + assertTrue(typeof sec === "number"); + assertTrue(typeof ms === "number"); + if (!Number.isFinite(hour) || !Number.isFinite(min) || !Number.isFinite(sec) || !Number.isFinite(ms)) { + return Number.NaN; + } + let h = ToInteger(hour); + let m = ToInteger(min); + let s = ToInteger(sec); + let milli = ToInteger(ms); + let t = h * msPerHour + m * msPerMinute + s * msPerSecond + milli; + return t; +} + +// 20.3.1.12 MakeDay (year, month, date) +function MakeDay(year, month, date) { + assertTrue(typeof year === "number"); + assertTrue(typeof month === "number"); + assertTrue(typeof date === "number"); + if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(date)) { + return Number.NaN; + } + let y = ToInteger(year); + let m = ToInteger(month); + let dt = ToInteger(date); + let ym = y + Math.floor(m / 12); + let mn = modulo(m, 12); + + const monthStart = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + let day = Math.floor(TimeFromYear(ym) / msPerDay) + monthStart[mn]; + if (mn >= 2 && DaysInYear(ym) == 366) { + day += 1; + } + + return day + dt - 1; +} + +// 20.3.1.13 MakeDate (day, time) +function MakeDate(day, time) { + assertTrue(typeof day === "number"); + assertTrue(typeof time === "number"); + if (!Number.isFinite(day) || !Number.isFinite(time)) { + return Number.NaN; + } + return day * msPerDay + time; +} + +// 20.3.1.14 TimeClip (time) +function TimeClip(time) { + assertTrue(typeof time === "number"); + if (!Number.isFinite(time)) { + return Number.NaN; + } + if (Math.abs(time) > 8.64e15) { + return Number.NaN; + } + return ToInteger(time) + (+0); +} + +const DayOfWeek = { + Sunday: 0, + Monday: 1, + Tuesday: 2, + Wednesday: 3, + Thursday: 4, + Friday: 5, + Saturday: 6, +}; + +const Month = { + January: 0, + February: 1, + March: 2, + April: 3, + May: 4, + June: 5, + July: 6, + August: 7, + September: 8, + October: 9, + November: 10, + December: 11, +}; + +const DateTime = { + Local: class { + constructor(year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0) { + Object.assign(this, {year, month, day, weekday, hour, minute, second, ms}); + } + + toDate() { + return new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms); + } + }, + UTC: class { + constructor(year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0) { + Object.assign(this, {year, month, day, weekday, hour, minute, second, ms}); + } + + toInstant() { + return MakeDate(MakeDay(this.year, this.month, this.day), MakeTime(this.hour, this.minute, this.second, this.ms)); + } + }, +}; + +function TimeZone(hour, minute = 0, second = 0) { + return new class TimeZone { + constructor(hour, minute, second) { + Object.assign(this, {hour, minute, second}); + } + + toOffset() { + let offset = TimeZoneOffset(this.hour, this.minute, this.second); + return offset !== 0 ? -offset : 0; + } + }(hour, minute, second); + + function TimeZoneOffset(hour, minute = 0, second = 0) { + assertTrue(typeof hour === "number"); + assertTrue(typeof minute === "number"); + assertTrue(typeof second === "number"); + assertTrue(minute >= 0); + assertTrue(second >= 0); + if (hour < 0 || Object.is(-0, hour)) { + return hour * MinutesPerHour - minute - (second / 60); + } + return hour * MinutesPerHour + minute + (second / 60); + } +} + +const Format = { + Locale: "en-US", + DateTime: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: "short", + era: void 0, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + formatMatcher: "best fit", + hour12: void 0, + }, + Date: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: "short", + era: void 0, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: void 0, + minute: void 0, + second: void 0, + timeZoneName: void 0, + formatMatcher: "best fit", + hour12: void 0, + }, + Time: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: void 0, + era: void 0, + year: void 0, + month: void 0, + day: void 0, + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + formatMatcher: "best fit", + hour12: void 0, + }, +}; + +return { + DayOfWeek, + Month, + DateTime, + TimeZone, + Format, +}; +})(); + + +// File: lib/assert-datetime.js + +function assertDate(local, utc, timeZone, options, formatArgs) { + let d = local.toDate(); + assertDateValue(d, utc.toInstant(), timeZone.toOffset()); + assertLocalDate(d, local); + assertUTCDate(d, utc); + assertDateString(d, options, formatArgs); +} + +function assertDateValue(actual, dateValue, timeZoneOffset) { + assertSame(dateValue, actual.valueOf(), `valueOf()[${dateValue - actual.valueOf()}]`); + assertSame(dateValue, actual.getTime(), `valueOf()[${dateValue - actual.getTime()}]`); + assertSame(timeZoneOffset, actual.getTimezoneOffset(), "getTimezoneOffset()"); +} + +function assertLocalDate(actual, {year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0}) { + assertSame(year, actual.getFullYear(), "getFullYear()"); + assertSame(month, actual.getMonth(), "getMonth()"); + assertSame(day, actual.getDate(), "getDate()"); + assertSame(weekday, actual.getDay(), "getDay()"); + assertSame(hour, actual.getHours(), "getHours()"); + assertSame(minute, actual.getMinutes(), "getMinutes()"); + assertSame(second, actual.getSeconds(), "getSeconds()"); + assertSame(ms, actual.getMilliseconds(), "getMilliseconds()"); +} + +function assertUTCDate(actual, {year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0}) { + assertSame(year, actual.getUTCFullYear(), "getUTCFullYear()"); + assertSame(month, actual.getUTCMonth(), "getUTCMonth()"); + assertSame(day, actual.getUTCDate(), "getUTCDate()"); + assertSame(weekday, actual.getUTCDay(), "getUTCDay()"); + assertSame(hour, actual.getUTCHours(), "getUTCHours()"); + assertSame(minute, actual.getUTCMinutes(), "getUTCMinutes()"); + assertSame(second, actual.getUTCSeconds(), "getUTCSeconds()"); + assertSame(ms, actual.getUTCMilliseconds(), "getUTCMilliseconds()"); +} + +function assertDateString(actual, options, formatArgs = { + LocaleString: [Format.Locale, Format.DateTime], + LocaleDateString: [Format.Locale, Format.Date], + LocaleTimeString: [Format.Locale, Format.Time], +}) { + for (var key of Object.keys(options)) { + var args = formatArgs[key] || []; + assertSame(options[key], actual[`to${key}`](...args), `to${key}()`); + } +} + + +// File: Date/Africa_Monrovia.js +// Liberia was the last country to switch to UTC based offsets (1972 May). + +inTimeZone("Africa/Monrovia", () => { +{ + let local = new DateTime.Local(1972, Month.January, 6, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 6, DayOfWeek.Thursday, 0, 44, 30); + + assertDate(local, utc, TimeZone(-0,44,30), { + String: "Thu Jan 06 1972 00:00:00 GMT-0044 (Greenwich Mean Time)", + UTCString: "Thu, 06 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 6, DayOfWeek.Thursday, 23, 59, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 43, 30); + + assertDate(local, utc, TimeZone(-0,44,30), { + String: "Thu Jan 06 1972 23:59:00 GMT-0044 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:43:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + + assertDateValue(local.toDate(), utc.toInstant(), TimeZone(+0).toOffset()); + + assertDateString(local.toDate(), { + String: "Fri Jan 07 1972 00:44:30 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + + assertDate(local, utc, TimeZone(+0), { + String: "Fri Jan 07 1972 00:44:30 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 45, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 45, 0); + + assertDate(local, utc, TimeZone(+0), { + String: "Fri Jan 07 1972 00:45:00 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:45:00 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 8, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 8, DayOfWeek.Saturday, 0, 0, 0); + + assertDate(local, utc, TimeZone(+0), { + String: "Sat Jan 08 1972 00:00:00 GMT+0000 (Greenwich Mean Time)", + UTCString: "Sat, 08 Jan 1972 00:00:00 GMT", + }); +} +}); + + +// File: Date/Africa_Monrovia.js +// Africa/Tripoli switched from +02:00 to +01:00 and back. + +inTimeZone("Africa/Tripoli", () => { +{ + // +02:00 (standard time) + let local = new DateTime.Local(2012, Month.November, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.October, 31, DayOfWeek.Wednesday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Thu Nov 01 2012 00:00:00 GMT+0200 (Eastern European Standard Time)", + UTCString: "Wed, 31 Oct 2012 22:00:00 GMT", + }); +} + +{ + // +01:00 (standard time) + let local = new DateTime.Local(2012, Month.December, 1, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.November, 30, DayOfWeek.Friday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1), { + String: "Sat Dec 01 2012 00:00:00 GMT+0100 (Eastern European Standard Time)", + UTCString: "Fri, 30 Nov 2012 23:00:00 GMT", + }); +} + +{ + // +01:00 (daylight savings) + let local = new DateTime.Local(2013, Month.October, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(2013, Month.September, 30, DayOfWeek.Monday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Tue Oct 01 2013 00:00:00 GMT+0200 (Eastern European Summer Time)", + UTCString: "Mon, 30 Sep 2013 22:00:00 GMT", + }); +} + +{ + // +02:00 (standard time) + let local = new DateTime.Local(2013, Month.November, 1, DayOfWeek.Friday, 0, 0, 0); + let utc = new DateTime.UTC(2013, Month.October, 31, DayOfWeek.Thursday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Fri Nov 01 2013 00:00:00 GMT+0200 (Eastern European Standard Time)", + UTCString: "Thu, 31 Oct 2013 22:00:00 GMT", + }); +} +}); + + +// File: Date/America_Caracas.js +// America/Caracas switched from -04:00 to -04:30 on 2007 Dec 9. + +inTimeZone("America/Caracas", () => { +{ + // -04:00 (standard time) + let local = new DateTime.Local(2007, Month.December, 5, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(2007, Month.December, 5, DayOfWeek.Wednesday, 4, 0, 0); + + assertDate(local, utc, TimeZone(-4), { + String: "Wed Dec 05 2007 00:00:00 GMT-0400 (Venezuela Time)", + DateString: "Wed Dec 05 2007", + TimeString: "00:00:00 GMT-0400 (Venezuela Time)", + UTCString: "Wed, 05 Dec 2007 04:00:00 GMT", + ISOString: "2007-12-05T04:00:00.000Z", + LocaleString: "Wed, 12/05/2007, 12:00:00 AM GMT-4", + LocaleDateString: "Wed, 12/05/2007", + LocaleTimeString: "12:00:00 AM GMT-4", + }); +} + +{ + // -04:30 (standard time) + let local = new DateTime.Local(2007, Month.December, 12, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(2007, Month.December, 12, DayOfWeek.Wednesday, 4, 30, 0); + + assertDate(local, utc, TimeZone(-4, 30), { + String: "Wed Dec 12 2007 00:00:00 GMT-0430 (Venezuela Time)", + DateString: "Wed Dec 12 2007", + TimeString: "00:00:00 GMT-0430 (Venezuela Time)", + UTCString: "Wed, 12 Dec 2007 04:30:00 GMT", + ISOString: "2007-12-12T04:30:00.000Z", + LocaleString: "Wed, 12/12/2007, 12:00:00 AM GMT-4:30", + LocaleDateString: "Wed, 12/12/2007", + LocaleTimeString: "12:00:00 AM GMT-4:30", + }); +} +}); + + +// File: Date/Australia_Lord_Howe.js +// Australia/Lord_Howe time zone offset is +10:30 and daylight savings amount is 00:30. + +inTimeZone("Australia/Lord_Howe", () => { +{ + // +10:30 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 13, 30, 0); + + assertDate(local, utc, TimeZone(+10,30), { + String: "Sun Aug 01 2010 00:00:00 GMT+1030 (Lord Howe Standard Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1030 (Lord Howe Standard Time)", + UTCString: "Sat, 31 Jul 2010 13:30:00 GMT", + ISOString: "2010-07-31T13:30:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+10:30", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+10:30", + }); +} + +{ + // +10:30 (daylight savings) + let local = new DateTime.Local(2010, Month.January, 3, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.January, 2, DayOfWeek.Saturday, 13, 0, 0); + + assertDate(local, utc, TimeZone(+11), { + String: "Sun Jan 03 2010 00:00:00 GMT+1100 (Lord Howe Daylight Time)", + DateString: "Sun Jan 03 2010", + TimeString: "00:00:00 GMT+1100 (Lord Howe Daylight Time)", + UTCString: "Sat, 02 Jan 2010 13:00:00 GMT", + ISOString: "2010-01-02T13:00:00.000Z", + LocaleString: "Sun, 01/03/2010, 12:00:00 AM GMT+11", + LocaleDateString: "Sun, 01/03/2010", + LocaleTimeString: "12:00:00 AM GMT+11", + }); +} +}); + + +// File: Date/Europe_Amsterdam.js +// Europe/Amsterdam as an example for mean time like timezones after LMT (AMT, NST). +// +// tzdata2022b changed Europe/Amsterdam into a link to Europe/Brussels. + +inTimeZone("Europe/Amsterdam", () => { +{ + let local = new DateTime.Local(1935, Month.January, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(1935, Month.January, 1, DayOfWeek.Tuesday, 0, 0, 0); + + assertDate(local, utc, TimeZone(+0,0,0), { + String: "Tue Jan 01 1935 00:00:00 GMT+0000 (Central European Standard Time)", + UTCString: "Tue, 01 Jan 1935 00:00:00 GMT", + }); +} + +{ + let local = new DateTime.Local(1935, Month.July, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1935, Month.June, 30, DayOfWeek.Sunday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1,0,0), { + String: "Mon Jul 01 1935 00:00:00 GMT+0100 (Central European Summer Time)", + UTCString: "Sun, 30 Jun 1935 23:00:00 GMT", + }); +} +}); + +// Use America/St_Johns as a replacement for the Europe/Amsterdam test case. +// +// Zone America/St_Johns as an example for mean time like timezones after LMT (NST, NDT). + +inTimeZone("America/St_Johns", () => { +{ + let local = new DateTime.Local(1917, Month.January, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1917, Month.January, 1, DayOfWeek.Monday, 3, 30, 52); + + assertDate(local, utc, TimeZone(-3,30,52), { + String: "Mon Jan 01 1917 00:00:00 GMT-0330 (Newfoundland Standard Time)", + UTCString: "Mon, 01 Jan 1917 03:30:52 GMT", + }); +} + +{ + let local = new DateTime.Local(1917, Month.July, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(1917, Month.July, 1, DayOfWeek.Sunday, 2, 30, 52); + + assertDate(local, utc, TimeZone(-2,30,52), { + String: "Sun Jul 01 1917 00:00:00 GMT-0230 (Newfoundland Daylight Time)", + UTCString: "Sun, 01 Jul 1917 02:30:52 GMT", + }); +} +}); + + +// File: Date/Europe_London.js + +inTimeZone("Europe/London", () => { +{ + // +01:00 (standard time) + let local = new DateTime.Local(1970, Month.January, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1969, Month.December, 31, DayOfWeek.Wednesday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1), { + String: "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)", + DateString: "Thu Jan 01 1970", + TimeString: "00:00:00 GMT+0100 (Greenwich Mean Time)", + UTCString: "Wed, 31 Dec 1969 23:00:00 GMT", + ISOString: "1969-12-31T23:00:00.000Z", + LocaleString: "Thu, 01/01/1970, 12:00:00 AM GMT+1", + LocaleDateString: "Thu, 01/01/1970", + LocaleTimeString: "12:00:00 AM GMT+1", + }); +} +}); + + +// File: Date/Europe_Moscow.js + +inTimeZone("Europe/Moscow", () => { +{ + let local = new DateTime.Local(1970, Month.January, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1969, Month.December, 31, DayOfWeek.Wednesday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Thu Jan 01 1970 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Thu Jan 01 1970", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Wed, 31 Dec 1969 21:00:00 GMT", + ISOString: "1969-12-31T21:00:00.000Z", + LocaleString: "Thu, 01/01/1970, 12:00:00 AM GMT+3", + LocaleDateString: "Thu, 01/01/1970", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +// Russia was in +02:00 starting on 1991-03-31 until 1992-01-19, +// while still observing DST (transitions 1991-03-31 and 1991-09-29). + +{ + // +03:00 (daylight savings) + let local = new DateTime.Local(1990, Month.September, 1, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1990, Month.August, 31, DayOfWeek.Friday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sat Sep 01 1990 00:00:00 GMT+0400 (Moscow Summer Time)", + DateString: "Sat Sep 01 1990", + TimeString: "00:00:00 GMT+0400 (Moscow Summer Time)", + UTCString: "Fri, 31 Aug 1990 20:00:00 GMT", + ISOString: "1990-08-31T20:00:00.000Z", + LocaleString: "Sat, 09/01/1990, 12:00:00 AM GMT+4", + LocaleDateString: "Sat, 09/01/1990", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(1991, Month.March, 25, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.March, 24, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Mar 25 1991 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Mar 25 1991", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 24 Mar 1991 21:00:00 GMT", + ISOString: "1991-03-24T21:00:00.000Z", + LocaleString: "Mon, 03/25/1991, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 03/25/1991", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +02:00 (daylight savings) + let local = new DateTime.Local(1991, Month.March, 31, DayOfWeek.Sunday, 12, 0, 0); + let utc = new DateTime.UTC(1991, Month.March, 31, DayOfWeek.Sunday, 9, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Sun Mar 31 1991 12:00:00 GMT+0300 (Moscow Summer Time)", + DateString: "Sun Mar 31 1991", + TimeString: "12:00:00 GMT+0300 (Moscow Summer Time)", + UTCString: "Sun, 31 Mar 1991 09:00:00 GMT", + ISOString: "1991-03-31T09:00:00.000Z", + LocaleString: "Sun, 03/31/1991, 12:00:00 PM GMT+3", + LocaleDateString: "Sun, 03/31/1991", + LocaleTimeString: "12:00:00 PM GMT+3", + }); +} + +{ + // +02:00 (daylight savings) + let local = new DateTime.Local(1991, Month.September, 28, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.September, 27, DayOfWeek.Friday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Sat Sep 28 1991 00:00:00 GMT+0300 (Moscow Summer Time)", + DateString: "Sat Sep 28 1991", + TimeString: "00:00:00 GMT+0300 (Moscow Summer Time)", + UTCString: "Fri, 27 Sep 1991 21:00:00 GMT", + ISOString: "1991-09-27T21:00:00.000Z", + LocaleString: "Sat, 09/28/1991, 12:00:00 AM GMT+3", + LocaleDateString: "Sat, 09/28/1991", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +02:00 (standard time) + let local = new DateTime.Local(1991, Month.September, 30, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.September, 29, DayOfWeek.Sunday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Mon Sep 30 1991 00:00:00 GMT+0200 (Moscow Standard Time)", + DateString: "Mon Sep 30 1991", + TimeString: "00:00:00 GMT+0200 (Moscow Standard Time)", + UTCString: "Sun, 29 Sep 1991 22:00:00 GMT", + ISOString: "1991-09-29T22:00:00.000Z", + LocaleString: "Mon, 09/30/1991, 12:00:00 AM GMT+2", + LocaleDateString: "Mon, 09/30/1991", + LocaleTimeString: "12:00:00 AM GMT+2", + }); +} + +// Russia stopped observing DST in Oct. 2010 (last transition on 2010-10-31), +// and changed timezone from +03:00 to +04:00 on 2011-03-27. + +{ + // +03:00 (daylight savings) + let local = new DateTime.Local(2010, Month.October, 30, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.October, 29, DayOfWeek.Friday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sat Oct 30 2010 00:00:00 GMT+0400 (Moscow Summer Time)", + DateString: "Sat Oct 30 2010", + TimeString: "00:00:00 GMT+0400 (Moscow Summer Time)", + UTCString: "Fri, 29 Oct 2010 20:00:00 GMT", + ISOString: "2010-10-29T20:00:00.000Z", + LocaleString: "Sat, 10/30/2010, 12:00:00 AM GMT+4", + LocaleDateString: "Sat, 10/30/2010", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(2010, Month.November, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.October, 31, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Nov 01 2010 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Nov 01 2010", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 31 Oct 2010 21:00:00 GMT", + ISOString: "2010-10-31T21:00:00.000Z", + LocaleString: "Mon, 11/01/2010, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 11/01/2010", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2011, Month.October, 30, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.October, 29, DayOfWeek.Saturday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sun Oct 30 2011 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Sun Oct 30 2011", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Sat, 29 Oct 2011 20:00:00 GMT", + ISOString: "2011-10-29T20:00:00.000Z", + LocaleString: "Sun, 10/30/2011, 12:00:00 AM GMT+4", + LocaleDateString: "Sun, 10/30/2011", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2011, Month.November, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.October, 31, DayOfWeek.Monday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Tue Nov 01 2011 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Tue Nov 01 2011", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Mon, 31 Oct 2011 20:00:00 GMT", + ISOString: "2011-10-31T20:00:00.000Z", + LocaleString: "Tue, 11/01/2011, 12:00:00 AM GMT+4", + LocaleDateString: "Tue, 11/01/2011", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +// Russia changed timezone from +04:00 to +03:00 on 2014-10-26. + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2014, Month.October, 26, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2014, Month.October, 25, DayOfWeek.Saturday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sun Oct 26 2014 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Sun Oct 26 2014", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Sat, 25 Oct 2014 20:00:00 GMT", + ISOString: "2014-10-25T20:00:00.000Z", + LocaleString: "Sun, 10/26/2014, 12:00:00 AM GMT+4", + LocaleDateString: "Sun, 10/26/2014", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(2014, Month.October, 27, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2014, Month.October, 26, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Oct 27 2014 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Oct 27 2014", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 26 Oct 2014 21:00:00 GMT", + ISOString: "2014-10-26T21:00:00.000Z", + LocaleString: "Mon, 10/27/2014, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 10/27/2014", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} +}); + + +// File: Date/Pacific_Apia.js +// Pacific/Apia switched from -11:00 to +13:00 on 2011 Dec 29 24:00. + +inTimeZone("Pacific/Apia", () => { +{ + // -11:00 (daylight savings) + let local = new DateTime.Local(2011, Month.December, 29, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.December, 29, DayOfWeek.Thursday, 10, 0, 0); + + assertDate(local, utc, TimeZone(-10), { + String: "Thu Dec 29 2011 00:00:00 GMT-1000 (Apia Daylight Time)", + DateString: "Thu Dec 29 2011", + TimeString: "00:00:00 GMT-1000 (Apia Daylight Time)", + UTCString: "Thu, 29 Dec 2011 10:00:00 GMT", + ISOString: "2011-12-29T10:00:00.000Z", + LocaleString: "Thu, 12/29/2011, 12:00:00 AM GMT-10", + LocaleDateString: "Thu, 12/29/2011", + LocaleTimeString: "12:00:00 AM GMT-10", + }); +} + +{ + // +13:00 (daylight savings) + let local = new DateTime.Local(2011, Month.December, 31, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.December, 30, DayOfWeek.Friday, 10, 0, 0); + + assertDate(local, utc, TimeZone(+14), { + String: "Sat Dec 31 2011 00:00:00 GMT+1400 (Apia Daylight Time)", + DateString: "Sat Dec 31 2011", + TimeString: "00:00:00 GMT+1400 (Apia Daylight Time)", + UTCString: "Fri, 30 Dec 2011 10:00:00 GMT", + ISOString: "2011-12-30T10:00:00.000Z", + LocaleString: "Sat, 12/31/2011, 12:00:00 AM GMT+14", + LocaleDateString: "Sat, 12/31/2011", + LocaleTimeString: "12:00:00 AM GMT+14", + }); +} + +{ + // +13:00 (standard time) + let local = new DateTime.Local(2012, Month.April, 2, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.April, 1, DayOfWeek.Sunday, 11, 0, 0); + + assertDate(local, utc, TimeZone(+13), { + String: "Mon Apr 02 2012 00:00:00 GMT+1300 (Apia Standard Time)", + DateString: "Mon Apr 02 2012", + TimeString: "00:00:00 GMT+1300 (Apia Standard Time)", + UTCString: "Sun, 01 Apr 2012 11:00:00 GMT", + ISOString: "2012-04-01T11:00:00.000Z", + LocaleString: "Mon, 04/02/2012, 12:00:00 AM GMT+13", + LocaleDateString: "Mon, 04/02/2012", + LocaleTimeString: "12:00:00 AM GMT+13", + }); +} +}); + + +// File: Date/Pacific_Chatham.js +// Pacific/Chatham time zone offset is 12:45. + +inTimeZone("Pacific/Chatham", () => { +{ + // +12:45 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 11, 15, 0); + + assertDate(local, utc, TimeZone(+12,45), { + String: "Sun Aug 01 2010 00:00:00 GMT+1245 (Chatham Standard Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1245 (Chatham Standard Time)", + UTCString: "Sat, 31 Jul 2010 11:15:00 GMT", + ISOString: "2010-07-31T11:15:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+12:45", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+12:45", + }); +} + +{ + // +12:45 (daylight savings) + let local = new DateTime.Local(2010, Month.January, 3, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.January, 2, DayOfWeek.Saturday, 10, 15, 0); + + assertDate(local, utc, TimeZone(+13,45), { + String: "Sun Jan 03 2010 00:00:00 GMT+1345 (Chatham Daylight Time)", + DateString: "Sun Jan 03 2010", + TimeString: "00:00:00 GMT+1345 (Chatham Daylight Time)", + UTCString: "Sat, 02 Jan 2010 10:15:00 GMT", + ISOString: "2010-01-02T10:15:00.000Z", + LocaleString: "Sun, 01/03/2010, 12:00:00 AM GMT+13:45", + LocaleDateString: "Sun, 01/03/2010", + LocaleTimeString: "12:00:00 AM GMT+13:45", + }); +} +}); + + +// File: Date/Pacific_Kiritimati.js +// Pacific/Kiritimati time zone offset is +14:00. + +inTimeZone("Pacific/Kiritimati", () => { +{ + // +14:00 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 10, 0, 0); + + assertDate(local, utc, TimeZone(+14), { + String: "Sun Aug 01 2010 00:00:00 GMT+1400 (Line Islands Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1400 (Line Islands Time)", + UTCString: "Sat, 31 Jul 2010 10:00:00 GMT", + ISOString: "2010-07-31T10:00:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+14", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+14", + }); +} + +// Pacific/Kiritimati time zone offset was -10:40 until Oct. 1979. + +{ + // -10:40 (standard time) + let local = new DateTime.Local(1975, Month.January, 1, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(1975, Month.January, 1, DayOfWeek.Wednesday, 10, 40, 0); + + assertDate(local, utc, TimeZone(-10,40), { + String: "Wed Jan 01 1975 00:00:00 GMT-1040 (Line Islands Time)", + DateString: "Wed Jan 01 1975", + TimeString: "00:00:00 GMT-1040 (Line Islands Time)", + UTCString: "Wed, 01 Jan 1975 10:40:00 GMT", + ISOString: "1975-01-01T10:40:00.000Z", + LocaleString: "Wed, 01/01/1975, 12:00:00 AM GMT-10:40", + LocaleDateString: "Wed, 01/01/1975", + LocaleTimeString: "12:00:00 AM GMT-10:40", + }); +} +}); + + +// File: Date/Pacifi_Niue.js +// Pacific/Niue time zone offset was -11:20 from 1952 through 1964. + +inTimeZone("Pacific/Niue", () => { +{ + // -11:20 (standard time) + let local = new DateTime.Local(1956, Month.January, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(1956, Month.January, 1, DayOfWeek.Sunday, 11, 20, 0); + + assertDate(local, utc, TimeZone(-11,20), { + String: "Sun Jan 01 1956 00:00:00 GMT-1120 (Niue Time)", + DateString: "Sun Jan 01 1956", + TimeString: "00:00:00 GMT-1120 (Niue Time)", + UTCString: "Sun, 01 Jan 1956 11:20:00 GMT", + ISOString: "1956-01-01T11:20:00.000Z", + LocaleString: "Sun, 01/01/1956, 12:00:00 AM GMT-11:20", + LocaleDateString: "Sun, 01/01/1956", + LocaleTimeString: "12:00:00 AM GMT-11:20", + }); +} +}); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-pedantic.js b/js/src/tests/non262/Date/time-zones-pedantic.js new file mode 100644 index 0000000000..c3445ed5fd --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-pedantic.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||xulRuntime.OS=="Darwin") -- Skip on OS X in addition to Windows + +// Contains the tests from "time-zones.js" which fail on OS X. + +// bug 637244 +inTimeZone("Asia/Novosibirsk", () => { + let dt1 = new Date(1984, Month.April, 1, -1); + assertDateTime(dt1, "Sat Mar 31 1984 23:00:00 GMT+0700 (NOVT)", "+07", "Novosibirsk Standard Time"); + + let dt2 = new Date(1984, Month.April, 1); + assertDateTime(dt2, "Sun Apr 01 1984 01:00:00 GMT+0800 (NOVST)", "+08", "Novosibirsk Summer Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-posix.js b/js/src/tests/non262/Date/time-zones-posix.js new file mode 100644 index 0000000000..c2d7cc20c9 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-posix.js @@ -0,0 +1,160 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"&&!xulRuntime.shell) -- Windows browser in automation doesn't pick up new time zones correctly + +// Repeats the test from "time-zones.js", but uses POSIX instead of IANA names +// for the time zones. This allows to run these tests on Windows, too. + +// From bug 1330149: +// +// Windows only supports a very limited set of IANA time zone names for the TZ +// environment variable. +// +// TZ format supported by Windows: "TZ=tzn[+|-]hh[:mm[:ss]][dzn]". +// +// Complete list of all IANA time zone ids matching that format. +// +// From tzdata's "northamerica" file: +// EST5EDT +// CST6CDT +// MST7MDT +// PST8PDT +// +// From tzdata's "backward" file: +// GMT+0 +// GMT-0 +// GMT0 +// +// Also supported on Windows even though they don't match the format listed +// above. +// +// From tzdata's "backward" file: +// UCT +// UTC +// +// From tzdata's "etcetera" file: +// GMT + + +// Perform the following replacements: +// America/New_York -> EST5EDT +// America/Chicago -> CST6CDT +// America/Denver -> MST7MDT +// America/Los_Angeles -> PST8PDT +// +// And remove any tests not matching one of the four time zones from above. + +// bug 294908 +inTimeZone("EST5EDT", () => { + let dt = new Date(2003, Month.April, 6, 2, 30, 00); + assertDateTime(dt, "Sun Apr 06 2003 03:30:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 610183 +inTimeZone("PST8PDT", () => { + let dt = new Date(2014, Month.November, 2, 1, 47, 42); + assertDateTime(dt, "Sun Nov 02 2014 01:47:42 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +// bug 629465 +inTimeZone("MST7MDT", () => { + let dt1 = new Date(Date.UTC(2015, Month.November, 1, 0, 0, 0) + 6 * msPerHour); + assertDateTime(dt1, "Sun Nov 01 2015 00:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt2 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 6 * msPerHour); + assertDateTime(dt2, "Sun Nov 01 2015 01:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt3 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 7 * msPerHour); + assertDateTime(dt3, "Sun Nov 01 2015 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); +}); + +// bug 742427 +inTimeZone("EST5EDT", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("MST7MDT", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); +}); +inTimeZone("EST5EDT", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 9, 0, 0, 0) + 5 * msPerHour); + assertDateTime(dt1, "Sun Mar 09 2008 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 9, 1, 0, 0) + 5 * msPerHour); + assertDateTime(dt2, "Sun Mar 09 2008 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 9, 4, 0, 0) + 4 * msPerHour); + assertDateTime(dt3, "Sun Mar 09 2008 04:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 802627 +inTimeZone("EST5EDT", () => { + let dt = new Date(0); + assertDateTime(dt, "Wed Dec 31 1969 19:00:00 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 879261 +inTimeZone("EST5EDT", () => { + let dt1 = new Date(1362891600000); + assertDateTime(dt1, "Sun Mar 10 2013 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(dt1.setHours(dt1.getHours() + 24)); + assertDateTime(dt2, "Mon Mar 11 2013 00:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("PST8PDT", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt2 = new Date(2014, Month.August, 1); + assertDateTime(dt2, "Fri Aug 01 2014 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); +inTimeZone("EST5EDT", () => { + let dt1 = new Date(2016, Month.October, 14, 3, 5, 9); + assertDateTime(dt1, "Fri Oct 14 2016 03:05:09 GMT-0400 (EDT)", "Eastern Daylight Time"); + + let dt2 = new Date(2016, Month.January, 9, 23, 26, 40); + assertDateTime(dt2, "Sat Jan 09 2016 23:26:40 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 1084547 +inTimeZone("EST5EDT", () => { + let dt = new Date(Date.parse("2014-11-02T02:00:00-04:00")); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + dt.setMilliseconds(0); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1303306 +inTimeZone("EST5EDT", () => { + let dt = new Date(2016, Month.September, 15, 16, 14, 48); + assertDateTime(dt, "Thu Sep 15 2016 16:14:48 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1317364 +inTimeZone("PST8PDT", () => { + let dt = new Date(2016, Month.March, 13, 2, 30, 0, 0); + assertDateTime(dt, "Sun Mar 13 2016 03:30:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2016, Month.January, 5, 0, 30, 30, 500); + assertDateTime(dt2, "Tue Jan 05 2016 00:30:30 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt3 = new Date(dt2.getTime()); + dt3.setMonth(dt2.getMonth() + 2); + dt3.setDate(dt2.getDate() + 7 + 1); + dt3.setHours(dt2.getHours() + 2); + + assertEq(dt3.getHours(), 3); +}); + +// bug 1355272 +inTimeZone("PST8PDT", () => { + let dt = new Date(2017, Month.April, 10, 17, 25, 07); + assertDateTime(dt, "Mon Apr 10 2017 17:25:07 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones.js b/js/src/tests/non262/Date/time-zones.js new file mode 100644 index 0000000000..da2b328be7 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones.js @@ -0,0 +1,261 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +// bug 158328 +inTimeZone("Europe/London", () => { + let dt1 = new Date(2002, Month.July, 19, 16, 10, 55); + assertDateTime(dt1, "Fri Jul 19 2002 16:10:55 GMT+0100 (BST)", "British Summer Time"); + + let dt2 = new Date(2009, Month.December, 24, 13, 44, 52); + assertDateTime(dt2, "Thu Dec 24 2009 13:44:52 GMT+0000 (GMT)", "Greenwich Mean Time"); +}); + +// bug 294908 +inTimeZone("America/New_York", () => { + let dt = new Date(2003, Month.April, 6, 2, 30, 00); + assertDateTime(dt, "Sun Apr 06 2003 03:30:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 610183 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2014, Month.November, 2, 1, 47, 42); + assertDateTime(dt, "Sun Nov 02 2014 01:47:42 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +// bug 629465 +inTimeZone("America/Denver", () => { + let dt1 = new Date(Date.UTC(2015, Month.November, 1, 0, 0, 0) + 6 * msPerHour); + assertDateTime(dt1, "Sun Nov 01 2015 00:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt2 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 6 * msPerHour); + assertDateTime(dt2, "Sun Nov 01 2015 01:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt3 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 7 * msPerHour); + assertDateTime(dt3, "Sun Nov 01 2015 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); +}); + +// bug 637244 +inTimeZone("Europe/Helsinki", () => { + let dt1 = new Date(2016, Month.March, 27, 2, 59); + assertDateTime(dt1, "Sun Mar 27 2016 02:59:00 GMT+0200 (EET)", "Eastern European Standard Time"); + + let dt2 = new Date(2016, Month.March, 27, 3, 0); + assertDateTime(dt2, "Sun Mar 27 2016 04:00:00 GMT+0300 (EEST)", "Eastern European Summer Time"); +}); + +// bug 718175 +inTimeZone("Europe/London", () => { + let dt = new Date(0); + assertEq(dt.getHours(), 1); +}); + +// bug 719274 +inTimeZone("Pacific/Auckland", () => { + let dt = new Date(2012, Month.January, 19, 12, 54, 27); + assertDateTime(dt, "Thu Jan 19 2012 12:54:27 GMT+1300 (NZDT)", "New Zealand Daylight Time"); +}); + +// bug 742427 +inTimeZone("Europe/Paris", () => { + let dt1 = new Date(2009, Month.March, 29, 1, 0, 0); + assertDateTime(dt1, "Sun Mar 29 2009 01:00:00 GMT+0100 (CET)", "Central European Standard Time"); + dt1.setHours(dt1.getHours() + 1); + assertDateTime(dt1, "Sun Mar 29 2009 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt2 = new Date(2010, Month.March, 29, 1, 0, 0); + assertDateTime(dt2, "Mon Mar 29 2010 01:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + dt2.setHours(dt2.getHours() + 1); + assertDateTime(dt2, "Mon Mar 29 2010 02:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); +inTimeZone("America/New_York", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("America/Denver", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 9, 0, 0, 0) + 5 * msPerHour); + assertDateTime(dt1, "Sun Mar 09 2008 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 9, 1, 0, 0) + 5 * msPerHour); + assertDateTime(dt2, "Sun Mar 09 2008 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 9, 4, 0, 0) + 4 * msPerHour); + assertDateTime(dt3, "Sun Mar 09 2008 04:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("Europe/Paris", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 30, 0, 0, 0) - 1 * msPerHour); + assertDateTime(dt1, "Sun Mar 30 2008 00:00:00 GMT+0100 (CET)", "Central European Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 30, 1, 0, 0) - 1 * msPerHour); + assertDateTime(dt2, "Sun Mar 30 2008 01:00:00 GMT+0100 (CET)", "Central European Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 30, 3, 0, 0) - 2 * msPerHour); + assertDateTime(dt3, "Sun Mar 30 2008 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt4 = new Date(Date.UTC(2008, Month.March, 30, 4, 0, 0) - 2 * msPerHour); + assertDateTime(dt4, "Sun Mar 30 2008 04:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); + +// bug 802627 +inTimeZone("America/New_York", () => { + let dt = new Date(0); + assertDateTime(dt, "Wed Dec 31 1969 19:00:00 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 819820 +inTimeZone("Europe/London", () => { + let dt1 = new Date(Date.UTC(2012, Month.October, 28, 0, 59, 59)); + assertDateTime(dt1, "Sun Oct 28 2012 01:59:59 GMT+0100 (BST)", "British Summer Time"); + + let dt2 = new Date(Date.UTC(2012, Month.October, 28, 1, 0, 0)); + assertDateTime(dt2, "Sun Oct 28 2012 01:00:00 GMT+0000 (GMT)", "Greenwich Mean Time"); + + let dt3 = new Date(Date.UTC(2012, Month.October, 28, 1, 59, 59)); + assertDateTime(dt3, "Sun Oct 28 2012 01:59:59 GMT+0000 (GMT)", "Greenwich Mean Time"); + + let dt4 = new Date(Date.UTC(2012, Month.October, 28, 2, 0, 0)); + assertDateTime(dt4, "Sun Oct 28 2012 02:00:00 GMT+0000 (GMT)", "Greenwich Mean Time"); +}); + +// bug 879261 +inTimeZone("America/New_York", () => { + let dt1 = new Date(1362891600000); + assertDateTime(dt1, "Sun Mar 10 2013 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(dt1.setHours(dt1.getHours() + 24)); + assertDateTime(dt2, "Mon Mar 11 2013 00:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("America/Los_Angeles", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt2 = new Date(2014, Month.August, 1); + assertDateTime(dt2, "Fri Aug 01 2014 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(2016, Month.October, 14, 3, 5, 9); + assertDateTime(dt1, "Fri Oct 14 2016 03:05:09 GMT-0400 (EDT)", "Eastern Daylight Time"); + + let dt2 = new Date(2016, Month.January, 9, 23, 26, 40); + assertDateTime(dt2, "Sat Jan 09 2016 23:26:40 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 994086 +inTimeZone("Europe/Vienna", () => { + let dt1 = new Date(2014, Month.March, 30, 2, 0); + assertDateTime(dt1, "Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt2 = new Date(2014, Month.March, 30, 3, 0); + assertDateTime(dt2, "Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt3 = new Date(2014, Month.March, 30, 4, 0); + assertDateTime(dt3, "Sun Mar 30 2014 04:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); + +// bug 1084434 +inTimeZone("America/Sao_Paulo", () => { + let dt = new Date(2014, Month.October, 19); + assertEq(dt.getDate(), 19); + assertEq(dt.getHours(), 1); + assertDateTime(dt, "Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)", "-02", "Brasilia Summer Time"); +}); + +// bug 1084547 +inTimeZone("America/New_York", () => { + let dt = new Date(Date.parse("2014-11-02T02:00:00-04:00")); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + dt.setMilliseconds(0); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1118690 +inTimeZone("Europe/London", () => { + let dt = new Date(1965, Month.January, 1); + assertEq(dt.getFullYear(), 1965); +}); + +// bug 1155096 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(1981, Month.March, 32); + assertEq(dt1.getDate(), 1); + + let dt2 = new Date(1982, Month.March, 32); + assertEq(dt2.getDate(), 1); + + let dt3 = new Date(1983, Month.March, 32); + assertEq(dt3.getDate(), 1); + + let dt4 = new Date(1984, Month.March, 32); + assertEq(dt4.getDate(), 1); +}); + +// bug 1284507 +inTimeZone("Atlantic/Azores", () => { + let dt1 = new Date(2017, Month.March, 25, 0, 0, 0); + assertDateTime(dt1, "Sat Mar 25 2017 00:00:00 GMT-0100 (AZOT)", "-01", "Azores Standard Time"); + + let dt2 = new Date(2016, Month.October, 30, 0, 0, 0); + assertDateTime(dt2, "Sun Oct 30 2016 00:00:00 GMT+0000 (AZOST)", "+00", "Azores Summer Time"); + + let dt3 = new Date(2016, Month.October, 30, 23, 0, 0); + assertDateTime(dt3, "Sun Oct 30 2016 23:00:00 GMT-0100 (AZOT)", "-01", "Azores Standard Time"); +}); + +// bug 1303306 +inTimeZone("America/New_York", () => { + let dt = new Date(2016, Month.September, 15, 16, 14, 48); + assertDateTime(dt, "Thu Sep 15 2016 16:14:48 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1317364 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2016, Month.March, 13, 2, 30, 0, 0); + assertDateTime(dt, "Sun Mar 13 2016 03:30:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2016, Month.January, 5, 0, 30, 30, 500); + assertDateTime(dt2, "Tue Jan 05 2016 00:30:30 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt3 = new Date(dt2.getTime()); + dt3.setMonth(dt2.getMonth() + 2); + dt3.setDate(dt2.getDate() + 7 + 1); + dt3.setHours(dt2.getHours() + 2); + + assertEq(dt3.getHours(), 3); +}); + +// bug 1335818 +inTimeZone("Asia/Jerusalem", () => { + let dt1 = new Date(2013, Month.March, 22, 1, 0, 0, 0); + assertDateTime(dt1, "Fri Mar 22 2013 01:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt2 = new Date(2013, Month.March, 22, 2, 0, 0, 0); + assertDateTime(dt2, "Fri Mar 22 2013 02:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt3 = new Date(2013, Month.March, 22, 3, 0, 0, 0); + assertDateTime(dt3, "Fri Mar 22 2013 03:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt4 = new Date(2013, Month.March, 29, 1, 0, 0, 0); + assertDateTime(dt4, "Fri Mar 29 2013 01:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt5 = new Date(2013, Month.March, 29, 2, 0, 0, 0); + assertDateTime(dt5, "Fri Mar 29 2013 03:00:00 GMT+0300 (IDT)", "Israel Daylight Time"); + + let dt6 = new Date(2013, Month.March, 29, 3, 0, 0, 0); + assertDateTime(dt6, "Fri Mar 29 2013 03:00:00 GMT+0300 (IDT)", "Israel Daylight Time"); +}); + +// bug 1355272 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2017, Month.April, 10, 17, 25, 07); + assertDateTime(dt, "Mon Apr 10 2017 17:25:07 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/timeclip.js b/js/src/tests/non262/Date/timeclip.js new file mode 100644 index 0000000000..50bde39e77 --- /dev/null +++ b/js/src/tests/non262/Date/timeclip.js @@ -0,0 +1,42 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 747197; +var summary = "TimeClip behavior for very large numbers"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function addToLimit(n) { return 8.64e15 + n; } + +assertEq(8.64e15 === addToLimit(0.0), true); +assertEq(8.64e15 === addToLimit(0.5), true); +assertEq(8.64e15 === addToLimit(0.5000000000000001), false); + +var times = + [Number.MAX_VALUE, + -Number.MAX_VALUE, + Infinity, + -Infinity, + addToLimit(0.5000000000000001), + -addToLimit(0.5000000000000001)]; + +for (var i = 0, len = times.length; i < len; i++) +{ + var d = new Date(); + assertEq(d.setTime(times[i]), NaN, "times[" + i + "]"); + assertEq(d.getTime(), NaN); + assertEq(d.valueOf(), NaN); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/toISOString-01.js b/js/src/tests/non262/Date/toISOString-01.js new file mode 100644 index 0000000000..cc300a6604 --- /dev/null +++ b/js/src/tests/non262/Date/toISOString-01.js @@ -0,0 +1,53 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 730831; +var summary = 'Date.prototype.toISOString returns an invalid ISO-8601 string'; + +print(BUGNUMBER + ": " + summary); + +function iso(t) { + return new Date(t).toISOString(); +} + +function utc(year, month, day, hour, minute, second, millis) { + var date = new Date(0); + date.setUTCFullYear(year, month - 1, day); + date.setUTCHours(hour, minute, second, millis); + return date.getTime(); +} + + +// Values around maximum date for simple iso format. +var maxDateSimple = utc(9999, 12, 31, 23, 59, 59, 999); +assertEq(iso(maxDateSimple - 1), "9999-12-31T23:59:59.998Z"); +assertEq(iso(maxDateSimple ), "9999-12-31T23:59:59.999Z"); +assertEq(iso(maxDateSimple + 1), "+010000-01-01T00:00:00.000Z"); + + +// Values around minimum date for simple iso format. +var minDateSimple = utc(0, 1, 1, 0, 0, 0, 0); +assertEq(iso(minDateSimple - 1), "-000001-12-31T23:59:59.999Z"); +assertEq(iso(minDateSimple ), "0000-01-01T00:00:00.000Z"); +assertEq(iso(minDateSimple + 1), "0000-01-01T00:00:00.001Z"); + + +// Values around maximum date for extended iso format. +var maxDateExtended = utc(+275760, 9, 13, 0, 0, 0, 0); +assertEq(maxDateExtended, +8.64e15); +assertEq(iso(maxDateExtended - 1), "+275760-09-12T23:59:59.999Z"); +assertEq(iso(maxDateExtended ), "+275760-09-13T00:00:00.000Z"); +assertThrowsInstanceOf(() => iso(maxDateExtended + 1), RangeError); + + +// Values around minimum date for extended iso format. +var minDateExtended = utc(-271821, 4, 20, 0, 0, 0, 0); +assertEq(minDateExtended, -8.64e15); +assertThrowsInstanceOf(() => iso(minDateExtended - 1), RangeError); +assertEq(iso(minDateExtended ), "-271821-04-20T00:00:00.000Z"); +assertEq(iso(minDateExtended + 1), "-271821-04-20T00:00:00.001Z"); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toISOString.js b/js/src/tests/non262/Date/toISOString.js new file mode 100644 index 0000000000..9eb4129345 --- /dev/null +++ b/js/src/tests/non262/Date/toISOString.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function throwsRangeError(t) { + try { + var date = new Date(); + date.setTime(t); + var r = date.toISOString(); + throw new Error("toISOString didn't throw, instead returned " + r); + } catch (err) { + assertEq(err instanceof RangeError, true, 'wrong error: ' + err); + return; + } + assertEq(0, 1, 'not good, nyan, nyan'); +} + +throwsRangeError(Infinity); +throwsRangeError(-Infinity); +throwsRangeError(NaN); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toJSON-01.js b/js/src/tests/non262/Date/toJSON-01.js new file mode 100644 index 0000000000..4a756aab54 --- /dev/null +++ b/js/src/tests/non262/Date/toJSON-01.js @@ -0,0 +1,238 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'toJSON-01.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584811; +var summary = "Date.prototype.toJSON isn't to spec"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var called; + +var dateToJSON = Date.prototype.toJSON; +assertEq(Date.prototype.hasOwnProperty("toJSON"), true); +assertEq(typeof dateToJSON, "function"); + +// brief test to exercise this outside of isolation, just for sanity +var invalidDate = new Date(); +invalidDate.setTime(NaN); +assertEq(JSON.stringify({ p: invalidDate }), '{"p":null}'); + + +/* 15.9.5.44 Date.prototype.toJSON ( key ) */ +assertEq(dateToJSON.length, 1); + +/* + * 1. Let O be the result of calling ToObject, giving it the this value as its + * argument. + */ +try +{ + dateToJSON.call(null); + throw new Error("should have thrown a TypeError"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToObject throws TypeError for null/undefined"); +} + +try +{ + dateToJSON.call(undefined); + throw new Error("should have thrown a TypeError"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToObject throws TypeError for null/undefined"); +} + + +/* + * 2. Let tv be ToPrimitive(O, hint Number). + * ...expands to: + * 1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf". + * 2. If IsCallable(valueOf) is true then, + * a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and + * an empty argument list. + * b. If val is a primitive value, return val. + * 3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString". + * 4. If IsCallable(toString) is true then, + * a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and + * an empty argument list. + * b. If str is a primitive value, return str. + * 5. Throw a TypeError exception. + */ +try +{ + var r = dateToJSON.call({ get valueOf() { throw 17; } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e, 17, "bad exception: " + e); +} + +called = false; +assertEq(dateToJSON.call({ valueOf: null, + toString: function() { called = true; return 12; }, + toISOString: function() { return "ohai"; } }), + "ohai"); +assertEq(called, true); + +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return 42; }, + toISOString: function() { return null; } }), + null); +assertEq(called, true); + +try +{ + called = false; + dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() { throw 42; } }); +} +catch (e) +{ + assertEq(called, true); + assertEq(e, 42, "bad exception: " + e); +} + +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() { return function() { return 8675309; }; }, + toISOString: function() { return true; } }), + true); +assertEq(called, true); + +var asserted = false; +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() + { + assertEq(called, true); + asserted = true; + return function() { return 8675309; }; + }, + toISOString: function() { return NaN; } }), + NaN); +assertEq(asserted, true); + +try +{ + var r = dateToJSON.call({ valueOf: null, toString: null, + get toISOString() + { + throw new Error("shouldn't have been gotten"); + } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + + +/* 3. If tv is a Number and is not finite, return null. */ +assertEq(dateToJSON.call({ valueOf: function() { return Infinity; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return NaN; } }), null); + +assertEq(dateToJSON.call({ valueOf: function() { return Infinity; }, + toISOString: function() { return {}; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; }, + toISOString: function() { return []; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return NaN; }, + toISOString: function() { return undefined; } }), null); + + +/* + * 4. Let toISO be the result of calling the [[Get]] internal method of O with + * argument "toISOString". + */ +try +{ + var r = dateToJSON.call({ get toISOString() { throw 42; } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e, 42, "bad exception: " + e); +} + + +/* 5. If IsCallable(toISO) is false, throw a TypeError exception. */ +try +{ + var r = dateToJSON.call({ toISOString: null }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: undefined }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: "oogabooga" }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: Math.PI }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + + +/* + * 6. Return the result of calling the [[Call]] internal method of toISO with O + * as the this value and an empty argument list. + */ +var o = + { + toISOString: function(a) + { + called = true; + assertEq(this, o); + assertEq(a, undefined); + assertEq(arguments.length, 0); + return obj; + } + }; +var obj = {}; +called = false; +assertEq(dateToJSON.call(o), obj, "should have gotten obj back"); +assertEq(called, true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Date/toPrimitive.js b/js/src/tests/non262/Date/toPrimitive.js new file mode 100644 index 0000000000..11346b1ae8 --- /dev/null +++ b/js/src/tests/non262/Date/toPrimitive.js @@ -0,0 +1,62 @@ +// ES6 20.3.4.45 Date.prototype[@@toPrimitive](hint) + +// The toPrimitive method throws if the this value isn't an object. +var toPrimitive = Date.prototype[Symbol.toPrimitive]; +assertThrowsInstanceOf(() => toPrimitive.call(undefined, "default"), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(3, "default"), TypeError); + +// It doesn't have to be a Date object, though. +var obj = { + toString() { return "str"; }, + valueOf() { return "val"; } +}; +assertEq(toPrimitive.call(obj, "number"), "val"); +assertEq(toPrimitive.call(obj, "string"), "str"); +assertEq(toPrimitive.call(obj, "default"), "str"); + +// It throws if the hint argument is missing or not one of the three allowed values. +assertThrowsInstanceOf(() => toPrimitive.call(obj), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, undefined), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, "boolean"), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, ["number"]), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, {toString() { throw "FAIL"; }}), TypeError); + +// The next few tests cover the OrdinaryToPrimitive algorithm, specified in +// ES6 7.1.1 ToPrimitive(input [, PreferredType]). + +// Date.prototype.toString or .valueOf can be overridden. +var dateobj = new Date(); +Date.prototype.toString = function () { + assertEq(this, dateobj); + return 14; +}; +Date.prototype.valueOf = function () { + return "92"; +}; +assertEq(dateobj[Symbol.toPrimitive]("number"), "92"); +assertEq(dateobj[Symbol.toPrimitive]("string"), 14); +assertEq(dateobj[Symbol.toPrimitive]("default"), 14); +assertEq(dateobj == 14, true); // equality comparison: passes "default" + +// If this.toString is a non-callable value, this.valueOf is called instead. +Date.prototype.toString = {}; +assertEq(dateobj[Symbol.toPrimitive]("string"), "92"); +assertEq(dateobj[Symbol.toPrimitive]("default"), "92"); + +// And vice versa. +Date.prototype.toString = function () { return 15; }; +Date.prototype.valueOf = "ponies"; +assertEq(dateobj[Symbol.toPrimitive]("number"), 15); + +// If neither is callable, it throws a TypeError. +Date.prototype.toString = "ponies"; +assertThrowsInstanceOf(() => dateobj[Symbol.toPrimitive]("default"), TypeError); + +// Surface features. +assertEq(toPrimitive.name, "[Symbol.toPrimitive]"); +var desc = Object.getOwnPropertyDescriptor(Date.prototype, Symbol.toPrimitive); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Date/toString-generic.js b/js/src/tests/non262/Date/toString-generic.js new file mode 100644 index 0000000000..1e1c1fee93 --- /dev/null +++ b/js/src/tests/non262/Date/toString-generic.js @@ -0,0 +1,15 @@ +var BUGNUMBER = 861219; +var summary = 'Date.prototype.toString is a generic function'; + +// Revised in ECMA 2018, Date.prototype.toString is no longer generic (bug 1381433). + +print(BUGNUMBER + ": " + summary); + +for (var thisValue of [{}, [], /foo/, Date.prototype, new Proxy(new Date(), {})]) + assertThrowsInstanceOf(() => Date.prototype.toString.call(thisValue), TypeError); + +for (var prim of [null, undefined, 0, 1.2, true, false, "foo", Symbol.iterator]) + assertThrowsInstanceOf(() => Date.prototype.toString.call(prim), TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toString-localized-posix.js b/js/src/tests/non262/Date/toString-localized-posix.js new file mode 100644 index 0000000000..b2314f60a5 --- /dev/null +++ b/js/src/tests/non262/Date/toString-localized-posix.js @@ -0,0 +1,71 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) -- Requires ICU time zone support + +// Date.prototype.toString includes a localized time zone name comment. + +// Repeats the test from "toString-localized.js", but uses POSIX instead of IANA +// names for the time zones. This allows to run these tests on Windows, too. + +inTimeZone("PST8PDT", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Pacific Daylight Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (heure d’été du Pacifique nord-américain)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Nordamerikanische Westküsten-Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (توقيت المحيط الهادي الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (北美太平洋夏令时间)"); + }); +}); + +for (let tz of ["UTC", "UCT"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Coordinated Universal Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (temps universel coordonné)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Koordinierte Weltzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (التوقيت العالمي المنسق)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (协调世界时)"); + }); + }); +} + +inTimeZone("GMT", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Greenwich Mean Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (heure moyenne de Greenwich)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Mittlere Greenwich-Zeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (توقيت غرينتش)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (格林尼治标准时间)"); + }); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toString-localized.js b/js/src/tests/non262/Date/toString-localized.js new file mode 100644 index 0000000000..6baa535e5e --- /dev/null +++ b/js/src/tests/non262/Date/toString-localized.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// Date.prototype.toString includes a localized time zone name comment. + +inTimeZone("Europe/Paris", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (Central European Summer Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (heure d’été d’Europe centrale)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (توقيت وسط أوروبا الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (中欧夏令时间)"); + }); +}); + +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Pacific Daylight Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (heure d’été du Pacifique nord-américain)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Nordamerikanische Westküsten-Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (توقيت المحيط الهادي الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (北美太平洋夏令时间)"); + }); +}); + +for (let tz of ["UTC", "UCT", "Zulu", "Universal", "Etc/UTC", "Etc/UCT", "Etc/Zulu", "Etc/Universal"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Coordinated Universal Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (temps universel coordonné)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Koordinierte Weltzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (التوقيت العالمي المنسق)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (协调世界时)"); + }); + }); +} + +for (let tz of ["GMT", "Etc/GMT"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Greenwich Mean Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (heure moyenne de Greenwich)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Mittlere Greenwich-Zeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (توقيت غرينتش)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (格林尼治标准时间)"); + }); + }); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/two-digit-years.js b/js/src/tests/non262/Date/two-digit-years.js new file mode 100644 index 0000000000..80cbc2ecef --- /dev/null +++ b/js/src/tests/non262/Date/two-digit-years.js @@ -0,0 +1,71 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +/* + * For the sake of cross compatibility with other implementations we + * implement date parsing heuristics which support single and double + * digit years. See bug: 1265136 + */ + +/************** + * BEGIN TEST * + **************/ + +for (let year of Array(100).keys()) { + for (let month of Array(12).keys()) { + for (let day of Array(31).keys()) { + let fullYear = year >= 50 ? year + 1900 : year + 2000; + let fullDate = new Date(`${month + 1}/${day + 1}/${fullYear}`); + + // mm/dd/yy + let d1 = new Date(`${month + 1}/${day + 1}/${year}`); + assertEq(d1.getTime(), fullDate.getTime()) + + // yy/mm/dd + let d2 = new Date(`${year}/${month + 1}/${day + 1}`); + if (year > 31) { + assertEq(d2.getTime(), fullDate.getTime()) + } else if (year > 12) { + assertEq(d2.getTime(), new Date(NaN).getTime()) + } + } + } +} + +assertEq(new Date("99/1/99").getTime(), new Date(NaN).getTime()); +assertEq(new Date("13/13/13").getTime(), new Date(NaN).getTime()); +assertEq(new Date("0/10/0").getTime(), new Date(NaN).getTime()); + +// Written months. +for (let year of Array(1000).keys()) { + let fullDate = new Date(`5/1/${year}`); + let d1 = new Date(`may 1 ${year}`); + let d2 = new Date(`1 may ${year}`); + let d3 = new Date(`1 ${year} may`); + + assertEq(d1.getTime(), fullDate.getTime()) + assertEq(d2.getTime(), fullDate.getTime()) + assertEq(d3.getTime(), fullDate.getTime()) + + if (year > 31) { + let d4 = new Date(`may ${year} 1`); + let d5 = new Date(`${year} may 1`); + let d6 = new Date(`${year} 1 may`); + + assertEq(d4.getTime(), fullDate.getTime()) + assertEq(d5.getTime(), fullDate.getTime()) + assertEq(d6.getTime(), fullDate.getTime()) + } +} + +assertEq(new Date("may 1999 1999").getTime(), new Date(NaN).getTime()); +assertEq(new Date("may 0 0").getTime(), new Date(NaN).getTime()); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); |