From aabd1766c953ca754b023e5bd7a00a37943ebf22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Wed, 3 Apr 2013 12:20:02 -0700 Subject: [PATCH] Bug 836404 - Provide better timezone support in jstests. r=jwalden --HG-- extra : rebase_source : 11267ba920def4077e843230cddb583cbe8bad6d --- js/src/tests/ecma/shell.js | 128 +++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 12 deletions(-) diff --git a/js/src/tests/ecma/shell.js b/js/src/tests/ecma/shell.js index 7198cb23aaa0..0a671e096650 100644 --- a/js/src/tests/ecma/shell.js +++ b/js/src/tests/ecma/shell.js @@ -8,6 +8,7 @@ * Date functions used by tests in Date suite * */ +var msPerYear = 31536000000; var msPerDay = 86400000; var HoursPerDay = 24; var MinutesPerHour = 60; @@ -15,11 +16,19 @@ var SecondsPerMinute = 60; var msPerSecond = 1000; var msPerMinute = 60000; // msPerSecond * SecondsPerMinute var msPerHour = 3600000; // msPerMinute * MinutesPerHour -var TZ_DIFF = getTimeZoneDiff(); // offset of tester's timezone from UTC -var TZ_ADJUST = TZ_DIFF * msPerHour; + var TZ_PST = -8; // offset of Pacific Standard Time from UTC +var TZ_DIFF_RAW = GetRawTimezoneOffset(); // raw offset of tester's timezone from UTC +var TZ_DIFF = GetTimezoneOffset(); // offset of tester's timezone from UTC +var PST_DIFF_RAW = TZ_DIFF_RAW - TZ_PST; // raw offset of tester's timezone from PST var PST_DIFF = TZ_DIFF - TZ_PST; // offset of tester's timezone from PST +var TZ_ADJUST = TZ_DIFF_RAW * msPerHour; var PST_ADJUST = TZ_PST * msPerHour; + +var DST_PERIOD = DaylightSavingPeriod(); // time period when DST is used +var DST_1970 = DaylightSavingObserved(1970); // Was DST observed in 1970? +var DST_1971 = DaylightSavingObserved(1971); // Was DST observed in 1971? + var TIME_0000 = (function () { // calculate time for year 0 for ( var time = 0, year = 1969; year >= 0; year-- ) { @@ -43,9 +52,71 @@ var TIME_NOW = now.valueOf(); //valueOf() is to accurate to the millisecond * 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 getTimeZoneDiff() +function GetRawTimezoneOffset() { - return -((new Date(2000, 1, 1)).getTimezoneOffset())/60; + var t1 = new Date(2000, 1, 1).getTimezoneOffset(); + var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); + if ((t1 - t2) >= 0) { + // 1) timezone without daylight saving time + // 2) northern hemisphere with daylight saving time + return -t1 / MinutesPerHour; + } else { + // 3) southern hemisphere with daylight saving time + return -t2 / MinutesPerHour; + } +} + +/* + * Returns the timezone offset, possibly including daylight saving time. + * (This function is only used to obtain the relative timezone offset to PST, + * see TZ_DIFF and PST_DIFF in adjustResultArray().) + */ +function GetTimezoneOffset() +{ + return -(new Date(2000, 1, 1).getTimezoneOffset()) / MinutesPerHour; +} + +/* + * Determine when daylight saving time is used in the current timezone. + */ +function DaylightSavingPeriod() +{ + var t1 = new Date(2000, 1, 1).getTimezoneOffset(); + var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); + if (t1 == t2) { + // timezone without daylight saving time + return 0; + } else if ((t1 - t2) > 0) { + // northern hemisphere with daylight saving time + return 1; + } else { + // southern hemisphere with daylight saving time + return -1; + } +} + +/* + * Test whether daylight time saving was observed in the supplied year + */ +function DaylightSavingObserved(y) +{ + var t1 = new Date(y, 1, 1).getTimezoneOffset(); + var t2 = new Date(y, 1 + 6, 1).getTimezoneOffset(); + return (t1 != t2); +} + +/* + * Don't apply DST near start of epoch unless absolutely necessary + */ +function IgnoreDaylightSaving(t) +{ + if ((0 <= t && t < msPerYear) && !DST_1970) { + return true; + } + if ((msPerYear <= t && t < 2*msPerYear) && !DST_1971) { + return true; + } + return false; } /* @@ -74,14 +145,18 @@ function adjustResultArray(ResultArray, msMode) { // The hard-coded UTC milliseconds from Time 0 derives from a UTC date. // Shift to the right by the offset between UTC and the tester. - var t = ResultArray[TIME] + TZ_DIFF*msPerHour; + if (IgnoreDaylightSaving(ResultArray[TIME])) { + var t = ResultArray[TIME] + TZ_DIFF_RAW*msPerHour; + } else { + var t = ResultArray[TIME] + TZ_DIFF*msPerHour; + } // Use our date arithmetic functions to determine the local hour, day, etc. ResultArray[HOURS] = HourFromTime(t); ResultArray[DAY] = WeekDay(t); ResultArray[DATE] = DateFromTime(t); ResultArray[MONTH] = MonthFromTime(t); - ResultArray[YEAR] = YearFromTime(t); + ResultArray[YEAR] = YearFromTime(t); } else { @@ -295,7 +370,7 @@ function msFromTime( t ) { return ( (ms < 0 ) ? msPerSecond + ms : ms ); } function LocalTZA() { - return ( TZ_DIFF * msPerHour ); + return ( TZ_DIFF_RAW * msPerHour ); } function UTC( t ) { return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); @@ -304,13 +379,27 @@ function LocalTime( t ) { return ( t + LocalTZA() + DaylightSavingTA(t) ); } function DaylightSavingTA( t ) { - t = t - LocalTZA(); + if (IgnoreDaylightSaving(t)) { + return 0; + } - var dst_start = GetDSTStart(t); - var dst_end = GetDSTEnd(t); + if (DST_PERIOD > 0) { + // northern hemisphere + var dst_start = GetDSTStart(t); + var dst_end = GetDSTEnd(t); - if ( t >= dst_start && t < dst_end ) - return msPerHour; + if ( t >= dst_start && t < dst_end ) + return msPerHour; + } else if (DST_PERIOD < 0) { + // southern hemisphere + var dst_start = GetDSTStart_Southern(t); + var dst_end = GetDSTEnd_Southern(t); + + if ( t >= dst_start && t < GetDSTEnd_Southern(t + msPerYear) ) + return msPerHour; + if ( t < dst_end && t >= GetDSTEnd_Southern(t - msPerYear) ) + return msPerHour; + } return 0; } @@ -416,6 +505,21 @@ function GetOldDSTEnd( t ) return (GetLastSundayInMonth(t, 9) + 2*msPerHour - LocalTZA()); } +/* + * Daylight saving time start/end date for 'Australia' + * (arbitrarily chosen as a representative for the southern hemisphere) + */ + +function GetDSTStart_Southern( t ) +{ + return (GetFirstSundayInMonth(t, 9) + 2*msPerHour - LocalTZA()); +} + +function GetDSTEnd_Southern( t ) +{ + return (GetFirstSundayInMonth(t, 3) + 2*msPerHour - LocalTZA()); +} + function MakeTime( hour, min, sec, ms ) { if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) { return Number.NaN;