function dateToComponentString(dt) { return [ dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate(), dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds() ].join(' '); } function utcDiffAtTime(dt) { var d1; // This is not exactly accurate but good enough for testing: // take the UTC components and use them as local ones and see // how much difference that makes. d1 = new Date(dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate(), dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds()); // Positive offset = local time is ahead of UTC (e.g. EET is // +7200e3 or +10800e3 return dt.getTime() - d1.getTime(); } /*=== date constructor as function string true string true string true string true string true ===*/ /* Date constructor called as a function: all arguments are ignored, equivalent * to 'new Date().toString()'. */ print('date constructor as function'); function dateConstructorAsFunctionTest() { var now = new Date().getTime(); var t; var obj; // toString() result should parse back to a Date, so we check it parses // back close to current time t = Date(); print(typeof t); print(Math.abs(Date.parse(t) - now) < 5000); // same test, but checks that arguments are properly ignored as required // in E5.1 Section 15.9.2.1. t = Date(2030, 1, 2, 3, 4, 5, 6); print(typeof t); print(Math.abs(Date.parse(t) - now) < 5000); // even invalid values must be ignored t = Date(-1e12, 1e12, 2e12, 3e12, 4e12, 5e12, 6e12); print(typeof t); print(Math.abs(Date.parse(t) - now) < 5000); // even values of invalid type t = Date('foo', 'bar', 'quux'); print(typeof t); print(Math.abs(Date.parse(t) - now) < 5000); // because no coercion happens, no side effects should trigger obj = { toString: function() { print('toString'); return 'toString' }, valueOf: function() { print('valueOf'); return 'valueOf' } }; t = Date(obj, obj, obj, obj, obj, obj, obj); print(typeof t); print(Math.abs(Date.parse(t) - now) < 5000); } try { dateConstructorAsFunctionTest(); } catch (e) { print(e.name); } /*=== date constructor tests true 1970 0 1 0 1 0 0 NaN NaN NaN NaN NaN NaN NaN Invalid Date 2013 3 1 0 0 0 0 2013 1 2 3 4 5 6 -200000 1 2 3 4 5 6 200000 1 2 3 4 5 6 -1 1 2 3 4 5 6 1900 1 2 3 4 5 6 1999 1 2 3 4 5 6 100 1 2 3 4 5 6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 2012 11 2 3 4 5 6 2014 0 2 3 4 5 6 NaN NaN NaN NaN NaN NaN NaN 2013 0 31 3 4 5 6 2013 2 4 3 4 5 6 NaN NaN NaN NaN NaN NaN NaN 2013 1 2 2 59 5 6 2013 1 2 3 24 5 6 NaN NaN NaN NaN NaN NaN NaN 2013 1 2 3 3 59 6 2013 1 2 3 5 0 6 NaN NaN NaN NaN NaN NaN NaN 2013 1 2 3 4 4 999 2013 1 2 3 4 6 0 NaN NaN NaN NaN NaN NaN NaN 2012 1 2 3 4 5 6 2012 1 2 3 4 5 6 2012 1 2 3 4 5 6 2012 1 2 3 4 5 0 2012 1 2 3 4 0 0 2012 1 2 3 0 0 0 2012 1 2 0 0 0 0 2012 1 1 0 0 0 0 ===*/ /* Date constructor tests */ print('date constructor tests'); function dateConstructorTest() { var d; function toUtcAndPrint(dt) { var utcDiff = utcDiffAtTime(dt); dt = new Date(dt.getTime() + utcDiff); // Now UTC time print(dateToComponentString(dt)); } // No arguments: current time d = new Date(); print(d.getUTCFullYear() >= 2000 && d.getUTCFullYear() <= 2100); // One argument d = new Date(60*1000); // 1970-01-01 00:01:00 print(dateToComponentString(d)); // One argument which doesn't parse d = new Date('foo'); print(dateToComponentString(d)); // One argument + an undefined argument counts as two arguments // Month is NaN -> time value is NaN -> Invalid Date d = new Date(2013, undefined); print(d); // Two or more arguments: year, month, etc // Note that these are interpreted as local time, so we compensate // the difference to ensure test result is independent of timezone d = new Date(2013, 3); toUtcAndPrint(d); d = new Date(2013, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); // try large (absolute) years d = new Date(-200000, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(200000, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); // special handling of year arguments 0...99 -> interpreted as 1900...1999 d = new Date(-1, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(0, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(99, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(100, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); // invalid component values -> NaN -> Invalid Date; // in many cases out-of-range values are allowed and "normalized" by // MakeDate / MakeTime d = new Date(300000, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(-300000, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date('foo', 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(2013, -1, 2, 3, 4, 5, 6); toUtcAndPrint(d); // out of range months affect year (see MakeDate), d = new Date(2013, 12, 2, 3, 4, 5, 6); toUtcAndPrint(d); // so these two result in valid dates d = new Date(2013, 'foo', 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(2013, 1, 0, 3, 4, 5, 6); toUtcAndPrint(d); // again, out of range days are allowed (MakeDate) d = new Date(2013, 1, 32, 3, 4, 5, 6); toUtcAndPrint(d); // -""- d = new Date(2013, 1, 'foo', 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(2013, 1, 2, 3, -1, 5, 6); toUtcAndPrint(d); // allowed d = new Date(2013, 1, 2, 3, 24, 5, 6); toUtcAndPrint(d); // -""- d = new Date(2013, 1, 2, 3, 'foo', 5, 6); toUtcAndPrint(d); d = new Date(2013, 1, 2, 3, 4, -1, 6); toUtcAndPrint(d); // allowed d = new Date(2013, 1, 2, 3, 4, 60, 6); toUtcAndPrint(d); // -""- d = new Date(2013, 1, 2, 3, 4, 'foo', 6); toUtcAndPrint(d); d = new Date(2013, 1, 2, 3, 4, 5, -1); toUtcAndPrint(d); // allowed d = new Date(2013, 1, 2, 3, 4, 5, 1000); toUtcAndPrint(d); // -""- d = new Date(2013, 1, 2, 3, 4, 5, 'foo'); toUtcAndPrint(d); // express a large timestamp with milliseconds only d = new Date(2012, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); // this ... d = new Date(2012, 0, 0, 0, 0, 0, 2862245006); toUtcAndPrint(d); // ... is equivalent to this // argument defaulting d = new Date(2012, 1, 2, 3, 4, 5, 6); toUtcAndPrint(d); d = new Date(2012, 1, 2, 3, 4, 5); toUtcAndPrint(d); d = new Date(2012, 1, 2, 3, 4); toUtcAndPrint(d); d = new Date(2012, 1, 2, 3); toUtcAndPrint(d); d = new Date(2012, 1, 2); toUtcAndPrint(d); d = new Date(2012, 1); toUtcAndPrint(d); } try { dateConstructorTest(); } catch (e) { print(e.name); }