summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Date
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/Date')
-rw-r--r--js/src/tests/non262/Date/15.9.4.2.js134
-rw-r--r--js/src/tests/non262/Date/15.9.5.5-02.js63
-rw-r--r--js/src/tests/non262/Date/15.9.5.5.js111
-rw-r--r--js/src/tests/non262/Date/15.9.5.6.js118
-rw-r--r--js/src/tests/non262/Date/15.9.5.7.js111
-rw-r--r--js/src/tests/non262/Date/UTC-convert-all-arguments.js70
-rw-r--r--js/src/tests/non262/Date/browser.js12
-rw-r--r--js/src/tests/non262/Date/constructor-convert-all-arguments.js70
-rw-r--r--js/src/tests/non262/Date/constructor-one-Date-argument.js40
-rw-r--r--js/src/tests/non262/Date/constructor-one-argument.js26
-rw-r--r--js/src/tests/non262/Date/dashed-date.js118
-rw-r--r--js/src/tests/non262/Date/defaultvalue.js190
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-1-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-2-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-3-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-4-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-5-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-6-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-7-of-8.js6
-rw-r--r--js/src/tests/non262/Date/dst-offset-caching-8-of-8.js6
-rw-r--r--js/src/tests/non262/Date/equality-to-boolean.js39
-rw-r--r--js/src/tests/non262/Date/fractions.js24
-rw-r--r--js/src/tests/non262/Date/non-iso.js81
-rw-r--r--js/src/tests/non262/Date/parse-from-tostring-methods.js31
-rw-r--r--js/src/tests/non262/Date/parse-time-zone.js10
-rw-r--r--js/src/tests/non262/Date/prototype-is-not-a-date.js15
-rw-r--r--js/src/tests/non262/Date/regress-188211.js27
-rw-r--r--js/src/tests/non262/Date/regress-301738-01.js97
-rw-r--r--js/src/tests/non262/Date/regress-309925-01.js15
-rw-r--r--js/src/tests/non262/Date/regress-309925-02.js15
-rw-r--r--js/src/tests/non262/Date/regress-346027.js27
-rw-r--r--js/src/tests/non262/Date/regress-346363.js28
-rw-r--r--js/src/tests/non262/Date/regress-452786.js30
-rw-r--r--js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js30
-rw-r--r--js/src/tests/non262/Date/setTime-argument-shortcircuiting.js147
-rw-r--r--js/src/tests/non262/Date/shell.js311
-rw-r--r--js/src/tests/non262/Date/time-components-negative-zero.js18
-rw-r--r--js/src/tests/non262/Date/time-zone-2038-pst.js43
-rw-r--r--js/src/tests/non262/Date/time-zone-etc_localetime.js29
-rw-r--r--js/src/tests/non262/Date/time-zone-path.js30
-rw-r--r--js/src/tests/non262/Date/time-zone-pst.js120
-rw-r--r--js/src/tests/non262/Date/time-zones-historic.js538
-rw-r--r--js/src/tests/non262/Date/time-zones-imported.js1020
-rw-r--r--js/src/tests/non262/Date/time-zones-pedantic.js15
-rw-r--r--js/src/tests/non262/Date/time-zones-posix.js160
-rw-r--r--js/src/tests/non262/Date/time-zones.js261
-rw-r--r--js/src/tests/non262/Date/timeclip.js42
-rw-r--r--js/src/tests/non262/Date/toISOString-01.js53
-rw-r--r--js/src/tests/non262/Date/toISOString.js24
-rw-r--r--js/src/tests/non262/Date/toJSON-01.js238
-rw-r--r--js/src/tests/non262/Date/toPrimitive.js62
-rw-r--r--js/src/tests/non262/Date/toString-generic.js15
-rw-r--r--js/src/tests/non262/Date/toString-localized-posix.js71
-rw-r--r--js/src/tests/non262/Date/toString-localized.js90
-rw-r--r--js/src/tests/non262/Date/two-digit-years.js71
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");