michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: /* michael@0: * Date functions used by tests in Date suite michael@0: * michael@0: */ michael@0: var msPerYear = 31536000000; michael@0: var msPerDay = 86400000; michael@0: var HoursPerDay = 24; michael@0: var MinutesPerHour = 60; michael@0: var SecondsPerMinute = 60; michael@0: var msPerSecond = 1000; michael@0: var msPerMinute = 60000; // msPerSecond * SecondsPerMinute michael@0: var msPerHour = 3600000; // msPerMinute * MinutesPerHour michael@0: michael@0: var TZ_PST = -8; // offset of Pacific Standard Time from UTC michael@0: var TZ_DIFF_RAW = GetRawTimezoneOffset(); // raw offset of tester's timezone from UTC michael@0: var TZ_DIFF = GetTimezoneOffset(); // offset of tester's timezone from UTC michael@0: var PST_DIFF_RAW = TZ_DIFF_RAW - TZ_PST; // raw offset of tester's timezone from PST michael@0: var PST_DIFF = TZ_DIFF - TZ_PST; // offset of tester's timezone from PST michael@0: var TZ_ADJUST = TZ_DIFF_RAW * msPerHour; michael@0: var PST_ADJUST = TZ_PST * msPerHour; michael@0: michael@0: var DST_PERIOD = DaylightSavingPeriod(); // time period when DST is used michael@0: var DST_1970 = DaylightSavingObserved(1970); // Was DST observed in 1970? michael@0: var DST_1971 = DaylightSavingObserved(1971); // Was DST observed in 1971? michael@0: michael@0: var TIME_0000 = (function () michael@0: { // calculate time for year 0 michael@0: for ( var time = 0, year = 1969; year >= 0; year-- ) { michael@0: time -= TimeInYear(year); michael@0: } michael@0: return time; michael@0: })(); michael@0: var TIME_1970 = 0; michael@0: var TIME_2000 = 946684800000; michael@0: var TIME_1900 = -2208988800000; michael@0: var UTC_FEB_29_2000 = TIME_2000 + 31*msPerDay + 28*msPerDay; michael@0: var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000) + TimeInYear(2001) + michael@0: TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004); michael@0: var now = new Date(); michael@0: var TIME_NOW = now.valueOf(); //valueOf() is to accurate to the millisecond michael@0: //Date.parse() is accurate only to the second michael@0: michael@0: /* michael@0: * Originally, the test suite used a hard-coded value TZ_DIFF = -8. michael@0: * But that was only valid for testers in the Pacific Standard Time Zone! michael@0: * We calculate the proper number dynamically for any tester. We just michael@0: * have to be careful not to use a date subject to Daylight Savings Time... michael@0: */ michael@0: function GetRawTimezoneOffset() michael@0: { michael@0: var t1 = new Date(2000, 1, 1).getTimezoneOffset(); michael@0: var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); michael@0: if ((t1 - t2) >= 0) { michael@0: // 1) timezone without daylight saving time michael@0: // 2) northern hemisphere with daylight saving time michael@0: return -t1 / MinutesPerHour; michael@0: } else { michael@0: // 3) southern hemisphere with daylight saving time michael@0: return -t2 / MinutesPerHour; michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * Returns the timezone offset, possibly including daylight saving time. michael@0: * (This function is only used to obtain the relative timezone offset to PST, michael@0: * see TZ_DIFF and PST_DIFF in adjustResultArray().) michael@0: */ michael@0: function GetTimezoneOffset() michael@0: { michael@0: return -(new Date(2000, 1, 1).getTimezoneOffset()) / MinutesPerHour; michael@0: } michael@0: michael@0: /* michael@0: * Determine when daylight saving time is used in the current timezone. michael@0: */ michael@0: function DaylightSavingPeriod() michael@0: { michael@0: var t1 = new Date(2000, 1, 1).getTimezoneOffset(); michael@0: var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); michael@0: if (t1 == t2) { michael@0: // timezone without daylight saving time michael@0: return 0; michael@0: } else if ((t1 - t2) > 0) { michael@0: // northern hemisphere with daylight saving time michael@0: return 1; michael@0: } else { michael@0: // southern hemisphere with daylight saving time michael@0: return -1; michael@0: } michael@0: } michael@0: michael@0: /* michael@0: * Test whether daylight time saving was observed in the supplied year michael@0: */ michael@0: function DaylightSavingObserved(y) michael@0: { michael@0: var t1 = new Date(y, 1, 1).getTimezoneOffset(); michael@0: var t2 = new Date(y, 1 + 6, 1).getTimezoneOffset(); michael@0: return (t1 != t2); michael@0: } michael@0: michael@0: /* michael@0: * Don't apply DST near start of epoch unless absolutely necessary michael@0: */ michael@0: function IgnoreDaylightSaving(t) michael@0: { michael@0: if ((0 <= t && t < msPerYear) && !DST_1970) { michael@0: return true; michael@0: } michael@0: if ((msPerYear <= t && t < 2*msPerYear) && !DST_1971) { michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: /* michael@0: * Date test "ResultArrays" are hard-coded for Pacific Standard Time. michael@0: * We must adjust them for the tester's own timezone - michael@0: */ michael@0: function adjustResultArray(ResultArray, msMode) michael@0: { michael@0: // If the tester's system clock is in PST, no need to continue - michael@0: // if (!PST_DIFF) {return;} michael@0: michael@0: /* The date testcases instantiate Date objects in two different ways: michael@0: * michael@0: * millisecond mode: e.g. dt = new Date(10000000); michael@0: * year-month-day mode: dt = new Date(2000, 5, 1, ...); michael@0: * michael@0: * In the first case, the date is measured from Time 0 in Greenwich (i.e. UTC). michael@0: * In the second case, it is measured with reference to the tester's local timezone. michael@0: * michael@0: * In the first case we must correct those values expected for local measurements, michael@0: * like dt.getHours() etc. No correction is necessary for dt.getUTCHours() etc. michael@0: * michael@0: * In the second case, it is exactly the other way around - michael@0: */ michael@0: if (msMode) michael@0: { michael@0: // The hard-coded UTC milliseconds from Time 0 derives from a UTC date. michael@0: // Shift to the right by the offset between UTC and the tester. michael@0: if (IgnoreDaylightSaving(ResultArray[TIME])) { michael@0: var t = ResultArray[TIME] + TZ_DIFF_RAW*msPerHour; michael@0: } else { michael@0: var t = ResultArray[TIME] + TZ_DIFF*msPerHour; michael@0: } michael@0: michael@0: // Use our date arithmetic functions to determine the local hour, day, etc. michael@0: ResultArray[HOURS] = HourFromTime(t); michael@0: ResultArray[DAY] = WeekDay(t); michael@0: ResultArray[DATE] = DateFromTime(t); michael@0: ResultArray[MONTH] = MonthFromTime(t); michael@0: ResultArray[YEAR] = YearFromTime(t); michael@0: } michael@0: else michael@0: { michael@0: // The hard-coded UTC milliseconds from Time 0 derives from a PST date. michael@0: // Shift to the left by the offset between PST and the tester. michael@0: var t = ResultArray[TIME] - PST_DIFF*msPerHour; michael@0: michael@0: // Use our date arithmetic functions to determine the UTC hour, day, etc. michael@0: ResultArray[TIME] = t; michael@0: ResultArray[UTC_HOURS] = HourFromTime(t); michael@0: ResultArray[UTC_DAY] = WeekDay(t); michael@0: ResultArray[UTC_DATE] = DateFromTime(t); michael@0: ResultArray[UTC_MONTH] = MonthFromTime(t); michael@0: ResultArray[UTC_YEAR] = YearFromTime(t); michael@0: } michael@0: } michael@0: michael@0: function Day( t ) { michael@0: return ( Math.floor(t/msPerDay ) ); michael@0: } michael@0: function DaysInYear( y ) { michael@0: if ( y % 4 != 0 ) { michael@0: return 365; michael@0: } michael@0: if ( (y % 4 == 0) && (y % 100 != 0) ) { michael@0: return 366; michael@0: } michael@0: if ( (y % 100 == 0) && (y % 400 != 0) ) { michael@0: return 365; michael@0: } michael@0: if ( (y % 400 == 0) ){ michael@0: return 366; michael@0: } else { michael@0: return "ERROR: DaysInYear(" + y + ") case not covered"; michael@0: } michael@0: } michael@0: function TimeInYear( y ) { michael@0: return ( DaysInYear(y) * msPerDay ); michael@0: } michael@0: function DayNumber( t ) { michael@0: return ( Math.floor( t / msPerDay ) ); michael@0: } michael@0: function TimeWithinDay( t ) { michael@0: michael@0: var r = t % msPerDay; michael@0: michael@0: if (r < 0) michael@0: { michael@0: r += msPerDay; michael@0: } michael@0: return r; michael@0: michael@0: } michael@0: function YearNumber( t ) { michael@0: } michael@0: function TimeFromYear( y ) { michael@0: return ( msPerDay * DayFromYear(y) ); michael@0: } michael@0: function DayFromYear( y ) { michael@0: return ( 365*(y-1970) + michael@0: Math.floor((y-1969)/4) - michael@0: Math.floor((y-1901)/100) + michael@0: Math.floor((y-1601)/400) ); michael@0: } michael@0: function InLeapYear( t ) { michael@0: if ( DaysInYear(YearFromTime(t)) == 365 ) { michael@0: return 0; michael@0: } michael@0: if ( DaysInYear(YearFromTime(t)) == 366 ) { michael@0: return 1; michael@0: } else { michael@0: return "ERROR: InLeapYear("+ t + ") case not covered"; michael@0: } michael@0: } michael@0: function YearFromTime( t ) { michael@0: t = Number( t ); michael@0: var sign = ( t < 0 ) ? -1 : 1; michael@0: var year = ( sign < 0 ) ? 1969 : 1970; michael@0: for ( var timeToTimeZero = t; ; ) { michael@0: // subtract the current year's time from the time that's left. michael@0: timeToTimeZero -= sign * TimeInYear(year) michael@0: michael@0: // if there's less than the current year's worth of time left, then break. michael@0: if ( sign < 0 ) { michael@0: if ( sign * timeToTimeZero <= 0 ) { michael@0: break; michael@0: } else { michael@0: year += sign; michael@0: } michael@0: } else { michael@0: if ( sign * timeToTimeZero < 0 ) { michael@0: break; michael@0: } else { michael@0: year += sign; michael@0: } michael@0: } michael@0: } michael@0: return ( year ); michael@0: } michael@0: function MonthFromTime( t ) { michael@0: // i know i could use switch but i'd rather not until it's part of ECMA michael@0: var day = DayWithinYear( t ); michael@0: var leap = InLeapYear(t); michael@0: michael@0: if ( (0 <= day) && (day < 31) ) { michael@0: return 0; michael@0: } michael@0: if ( (31 <= day) && (day < (59+leap)) ) { michael@0: return 1; michael@0: } michael@0: if ( ((59+leap) <= day) && (day < (90+leap)) ) { michael@0: return 2; michael@0: } michael@0: if ( ((90+leap) <= day) && (day < (120+leap)) ) { michael@0: return 3; michael@0: } michael@0: if ( ((120+leap) <= day) && (day < (151+leap)) ) { michael@0: return 4; michael@0: } michael@0: if ( ((151+leap) <= day) && (day < (181+leap)) ) { michael@0: return 5; michael@0: } michael@0: if ( ((181+leap) <= day) && (day < (212+leap)) ) { michael@0: return 6; michael@0: } michael@0: if ( ((212+leap) <= day) && (day < (243+leap)) ) { michael@0: return 7; michael@0: } michael@0: if ( ((243+leap) <= day) && (day < (273+leap)) ) { michael@0: return 8; michael@0: } michael@0: if ( ((273+leap) <= day) && (day < (304+leap)) ) { michael@0: return 9; michael@0: } michael@0: if ( ((304+leap) <= day) && (day < (334+leap)) ) { michael@0: return 10; michael@0: } michael@0: if ( ((334+leap) <= day) && (day < (365+leap)) ) { michael@0: return 11; michael@0: } else { michael@0: return "ERROR: MonthFromTime("+t+") not known"; michael@0: } michael@0: } michael@0: function DayWithinYear( t ) { michael@0: return( Day(t) - DayFromYear(YearFromTime(t))); michael@0: } michael@0: function DateFromTime( t ) { michael@0: var day = DayWithinYear(t); michael@0: var month = MonthFromTime(t); michael@0: michael@0: if ( month == 0 ) { michael@0: return ( day + 1 ); michael@0: } michael@0: if ( month == 1 ) { michael@0: return ( day - 30 ); michael@0: } michael@0: if ( month == 2 ) { michael@0: return ( day - 58 - InLeapYear(t) ); michael@0: } michael@0: if ( month == 3 ) { michael@0: return ( day - 89 - InLeapYear(t)); michael@0: } michael@0: if ( month == 4 ) { michael@0: return ( day - 119 - InLeapYear(t)); michael@0: } michael@0: if ( month == 5 ) { michael@0: return ( day - 150- InLeapYear(t)); michael@0: } michael@0: if ( month == 6 ) { michael@0: return ( day - 180- InLeapYear(t)); michael@0: } michael@0: if ( month == 7 ) { michael@0: return ( day - 211- InLeapYear(t)); michael@0: } michael@0: if ( month == 8 ) { michael@0: return ( day - 242- InLeapYear(t)); michael@0: } michael@0: if ( month == 9 ) { michael@0: return ( day - 272- InLeapYear(t)); michael@0: } michael@0: if ( month == 10 ) { michael@0: return ( day - 303- InLeapYear(t)); michael@0: } michael@0: if ( month == 11 ) { michael@0: return ( day - 333- InLeapYear(t)); michael@0: } michael@0: michael@0: return ("ERROR: DateFromTime("+t+") not known" ); michael@0: } michael@0: function WeekDay( t ) { michael@0: var weekday = (Day(t)+4) % 7; michael@0: return( weekday < 0 ? 7 + weekday : weekday ); michael@0: } michael@0: michael@0: // missing daylight savings time adjustment michael@0: michael@0: function HourFromTime( t ) { michael@0: var h = Math.floor( t / msPerHour ) % HoursPerDay; michael@0: return ( (h<0) ? HoursPerDay + h : h ); michael@0: } michael@0: function MinFromTime( t ) { michael@0: var min = Math.floor( t / msPerMinute ) % MinutesPerHour; michael@0: return( ( min < 0 ) ? MinutesPerHour + min : min ); michael@0: } michael@0: function SecFromTime( t ) { michael@0: var sec = Math.floor( t / msPerSecond ) % SecondsPerMinute; michael@0: return ( (sec < 0 ) ? SecondsPerMinute + sec : sec ); michael@0: } michael@0: function msFromTime( t ) { michael@0: var ms = t % msPerSecond; michael@0: return ( (ms < 0 ) ? msPerSecond + ms : ms ); michael@0: } michael@0: function LocalTZA() { michael@0: return ( TZ_DIFF_RAW * msPerHour ); michael@0: } michael@0: function UTC( t ) { michael@0: return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); michael@0: } michael@0: function LocalTime( t ) { michael@0: return ( t + LocalTZA() + DaylightSavingTA(t) ); michael@0: } michael@0: function DaylightSavingTA( t ) { michael@0: if (IgnoreDaylightSaving(t)) { michael@0: return 0; michael@0: } michael@0: michael@0: if (DST_PERIOD > 0) { michael@0: // northern hemisphere michael@0: var dst_start = GetDSTStart(t); michael@0: var dst_end = GetDSTEnd(t); michael@0: michael@0: if ( t >= dst_start && t < dst_end ) michael@0: return msPerHour; michael@0: } else if (DST_PERIOD < 0) { michael@0: // southern hemisphere michael@0: var dst_start = GetDSTStart_Southern(t); michael@0: var dst_end = GetDSTEnd_Southern(t); michael@0: michael@0: if ( t >= dst_start && t < GetDSTEnd_Southern(t + msPerYear) ) michael@0: return msPerHour; michael@0: if ( t < dst_end && t >= GetDSTEnd_Southern(t - msPerYear) ) michael@0: return msPerHour; michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: function GetFirstSundayInMonth( t, m ) { michael@0: var year = YearFromTime(t); michael@0: var leap = InLeapYear(t); michael@0: michael@0: // month m 0..11 michael@0: // april == 3 michael@0: // march == 2 michael@0: michael@0: // set time to first day of month m michael@0: var time = TimeFromYear(year); michael@0: for (var i = 0; i < m; ++i) michael@0: { michael@0: time += TimeInMonth(i, leap); michael@0: } michael@0: michael@0: for ( var first_sunday = time; WeekDay(first_sunday) > 0; michael@0: first_sunday += msPerDay ) michael@0: { michael@0: ; michael@0: } michael@0: michael@0: return first_sunday; michael@0: } michael@0: michael@0: function GetLastSundayInMonth( t, m ) { michael@0: var year = YearFromTime(t); michael@0: var leap = InLeapYear(t); michael@0: michael@0: // month m 0..11 michael@0: // april == 3 michael@0: // march == 2 michael@0: michael@0: // first day of following month michael@0: var time = TimeFromYear(year); michael@0: for (var i = 0; i <= m; ++i) michael@0: { michael@0: time += TimeInMonth(i, leap); michael@0: } michael@0: // prev day == last day of month michael@0: time -= msPerDay; michael@0: michael@0: for ( var last_sunday = time; WeekDay(last_sunday) > 0; michael@0: last_sunday -= msPerDay ) michael@0: { michael@0: ; michael@0: } michael@0: return last_sunday; michael@0: } michael@0: michael@0: /* michael@0: 15.9.1.9 Daylight Saving Time Adjustment michael@0: michael@0: The implementation of ECMAScript should not try to determine whether michael@0: the exact time was subject to daylight saving time, but just whether michael@0: daylight saving time would have been in effect if the current michael@0: daylight saving time algorithm had been used at the time. This avoids michael@0: complications such as taking into account the years that the locale michael@0: observed daylight saving time year round. michael@0: */ michael@0: michael@0: /* michael@0: US DST algorithm michael@0: michael@0: Before 2007, DST starts first Sunday in April at 2 AM and ends last michael@0: Sunday in October at 2 AM michael@0: michael@0: Starting in 2007, DST starts second Sunday in March at 2 AM and ends michael@0: first Sunday in November at 2 AM michael@0: michael@0: Note that different operating systems behave differently. michael@0: michael@0: Fully patched Windows XP uses the 2007 algorithm for all dates while michael@0: fully patched Fedora Core 6 and RHEL 4 Linux use the algorithm in michael@0: effect at the time. michael@0: michael@0: Since pre-2007 DST is a subset of 2007 DST rules, this only affects michael@0: tests that occur in the period Mar-Apr and Oct-Nov where the two michael@0: algorithms do not agree. michael@0: michael@0: */ michael@0: michael@0: function GetDSTStart( t ) michael@0: { michael@0: return (GetFirstSundayInMonth(t, 2) + 7*msPerDay + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: function GetDSTEnd( t ) michael@0: { michael@0: return (GetFirstSundayInMonth(t, 10) + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: function GetOldDSTStart( t ) michael@0: { michael@0: return (GetFirstSundayInMonth(t, 3) + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: function GetOldDSTEnd( t ) michael@0: { michael@0: return (GetLastSundayInMonth(t, 9) + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: /* michael@0: * Daylight saving time start/end date for 'Australia' michael@0: * (arbitrarily chosen as a representative for the southern hemisphere) michael@0: */ michael@0: michael@0: function GetDSTStart_Southern( t ) michael@0: { michael@0: return (GetFirstSundayInMonth(t, 9) + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: function GetDSTEnd_Southern( t ) michael@0: { michael@0: return (GetFirstSundayInMonth(t, 3) + 2*msPerHour - LocalTZA()); michael@0: } michael@0: michael@0: function MakeTime( hour, min, sec, ms ) { michael@0: if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) { michael@0: return Number.NaN; michael@0: } michael@0: michael@0: hour = ToInteger(hour); michael@0: min = ToInteger( min); michael@0: sec = ToInteger( sec); michael@0: ms = ToInteger( ms ); michael@0: michael@0: return( (hour*msPerHour) + (min*msPerMinute) + michael@0: (sec*msPerSecond) + ms ); michael@0: } michael@0: function MakeDay( year, month, date ) { michael@0: if ( isNaN(year) || isNaN(month) || isNaN(date) ) { michael@0: return Number.NaN; michael@0: } michael@0: year = ToInteger(year); michael@0: month = ToInteger(month); michael@0: date = ToInteger(date ); michael@0: michael@0: var sign = ( year < 1970 ) ? -1 : 1; michael@0: var t = ( year < 1970 ) ? 1 : 0; michael@0: var y = ( year < 1970 ) ? 1969 : 1970; michael@0: michael@0: var result5 = year + Math.floor( month/12 ); michael@0: var result6 = month % 12; michael@0: michael@0: if ( year < 1970 ) { michael@0: for ( y = 1969; y >= year; y += sign ) { michael@0: t += sign * TimeInYear(y); michael@0: } michael@0: } else { michael@0: for ( y = 1970 ; y < year; y += sign ) { michael@0: t += sign * TimeInYear(y); michael@0: } michael@0: } michael@0: michael@0: var leap = InLeapYear( t ); michael@0: michael@0: for ( var m = 0; m < month; m++ ) { michael@0: t += TimeInMonth( m, leap ); michael@0: } michael@0: michael@0: if ( YearFromTime(t) != result5 ) { michael@0: return Number.NaN; michael@0: } michael@0: if ( MonthFromTime(t) != result6 ) { michael@0: return Number.NaN; michael@0: } michael@0: if ( DateFromTime(t) != 1 ) { michael@0: return Number.NaN; michael@0: } michael@0: michael@0: return ( (Day(t)) + date - 1 ); michael@0: } michael@0: function TimeInMonth( month, leap ) { michael@0: // september april june november michael@0: // jan 0 feb 1 mar 2 apr 3 may 4 june 5 jul 6 michael@0: // aug 7 sep 8 oct 9 nov 10 dec 11 michael@0: michael@0: if ( month == 3 || month == 5 || month == 8 || month == 10 ) { michael@0: return ( 30*msPerDay ); michael@0: } michael@0: michael@0: // all the rest michael@0: if ( month == 0 || month == 2 || month == 4 || month == 6 || michael@0: month == 7 || month == 9 || month == 11 ) { michael@0: return ( 31*msPerDay ); michael@0: } michael@0: michael@0: // save february michael@0: return ( (leap == 0) ? 28*msPerDay : 29*msPerDay ); michael@0: } michael@0: function MakeDate( day, time ) { michael@0: if ( day == Number.POSITIVE_INFINITY || michael@0: day == Number.NEGATIVE_INFINITY ) { michael@0: return Number.NaN; michael@0: } michael@0: if ( time == Number.POSITIVE_INFINITY || michael@0: time == Number.NEGATIVE_INFINITY ) { michael@0: return Number.NaN; michael@0: } michael@0: return ( day * msPerDay ) + time; michael@0: } michael@0: function TimeClip( t ) { michael@0: if ( isNaN( t ) ) { michael@0: return ( Number.NaN ); michael@0: } michael@0: if ( Math.abs( t ) > 8.64e15 ) { michael@0: return ( Number.NaN ); michael@0: } michael@0: michael@0: return ( ToInteger( t ) ); michael@0: } michael@0: function ToInteger( t ) { michael@0: t = Number( t ); michael@0: michael@0: if ( isNaN( t ) ){ michael@0: return ( Number.NaN ); michael@0: } michael@0: if ( t == 0 || t == -0 || michael@0: t == Number.POSITIVE_INFINITY || t == Number.NEGATIVE_INFINITY ) { michael@0: return 0; michael@0: } michael@0: michael@0: var sign = ( t < 0 ) ? -1 : 1; michael@0: michael@0: return ( sign * Math.floor( Math.abs( t ) ) ); michael@0: } michael@0: function Enumerate ( o ) { michael@0: var p; michael@0: for ( p in o ) { michael@0: print( p +": " + o[p] ); michael@0: } michael@0: } michael@0: michael@0: /* these functions are useful for running tests manually in Rhino */ michael@0: michael@0: function GetContext() { michael@0: return Packages.com.netscape.javascript.Context.getCurrentContext(); michael@0: } michael@0: function OptLevel( i ) { michael@0: i = Number(i); michael@0: var cx = GetContext(); michael@0: cx.setOptimizationLevel(i); michael@0: } michael@0: /* end of Rhino functions */ michael@0: