Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * Date functions used by tests in Date suite
9 *
10 */
11 var msPerYear = 31536000000;
12 var msPerDay = 86400000;
13 var HoursPerDay = 24;
14 var MinutesPerHour = 60;
15 var SecondsPerMinute = 60;
16 var msPerSecond = 1000;
17 var msPerMinute = 60000; // msPerSecond * SecondsPerMinute
18 var msPerHour = 3600000; // msPerMinute * MinutesPerHour
20 var TZ_PST = -8; // offset of Pacific Standard Time from UTC
21 var TZ_DIFF_RAW = GetRawTimezoneOffset(); // raw offset of tester's timezone from UTC
22 var TZ_DIFF = GetTimezoneOffset(); // offset of tester's timezone from UTC
23 var PST_DIFF_RAW = TZ_DIFF_RAW - TZ_PST; // raw offset of tester's timezone from PST
24 var PST_DIFF = TZ_DIFF - TZ_PST; // offset of tester's timezone from PST
25 var TZ_ADJUST = TZ_DIFF_RAW * msPerHour;
26 var PST_ADJUST = TZ_PST * msPerHour;
28 var DST_PERIOD = DaylightSavingPeriod(); // time period when DST is used
29 var DST_1970 = DaylightSavingObserved(1970); // Was DST observed in 1970?
30 var DST_1971 = DaylightSavingObserved(1971); // Was DST observed in 1971?
32 var TIME_0000 = (function ()
33 { // calculate time for year 0
34 for ( var time = 0, year = 1969; year >= 0; year-- ) {
35 time -= TimeInYear(year);
36 }
37 return time;
38 })();
39 var TIME_1970 = 0;
40 var TIME_2000 = 946684800000;
41 var TIME_1900 = -2208988800000;
42 var UTC_FEB_29_2000 = TIME_2000 + 31*msPerDay + 28*msPerDay;
43 var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000) + TimeInYear(2001) +
44 TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004);
45 var now = new Date();
46 var TIME_NOW = now.valueOf(); //valueOf() is to accurate to the millisecond
47 //Date.parse() is accurate only to the second
49 /*
50 * Originally, the test suite used a hard-coded value TZ_DIFF = -8.
51 * But that was only valid for testers in the Pacific Standard Time Zone!
52 * We calculate the proper number dynamically for any tester. We just
53 * have to be careful not to use a date subject to Daylight Savings Time...
54 */
55 function GetRawTimezoneOffset()
56 {
57 var t1 = new Date(2000, 1, 1).getTimezoneOffset();
58 var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset();
59 if ((t1 - t2) >= 0) {
60 // 1) timezone without daylight saving time
61 // 2) northern hemisphere with daylight saving time
62 return -t1 / MinutesPerHour;
63 } else {
64 // 3) southern hemisphere with daylight saving time
65 return -t2 / MinutesPerHour;
66 }
67 }
69 /*
70 * Returns the timezone offset, possibly including daylight saving time.
71 * (This function is only used to obtain the relative timezone offset to PST,
72 * see TZ_DIFF and PST_DIFF in adjustResultArray().)
73 */
74 function GetTimezoneOffset()
75 {
76 return -(new Date(2000, 1, 1).getTimezoneOffset()) / MinutesPerHour;
77 }
79 /*
80 * Determine when daylight saving time is used in the current timezone.
81 */
82 function DaylightSavingPeriod()
83 {
84 var t1 = new Date(2000, 1, 1).getTimezoneOffset();
85 var t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset();
86 if (t1 == t2) {
87 // timezone without daylight saving time
88 return 0;
89 } else if ((t1 - t2) > 0) {
90 // northern hemisphere with daylight saving time
91 return 1;
92 } else {
93 // southern hemisphere with daylight saving time
94 return -1;
95 }
96 }
98 /*
99 * Test whether daylight time saving was observed in the supplied year
100 */
101 function DaylightSavingObserved(y)
102 {
103 var t1 = new Date(y, 1, 1).getTimezoneOffset();
104 var t2 = new Date(y, 1 + 6, 1).getTimezoneOffset();
105 return (t1 != t2);
106 }
108 /*
109 * Don't apply DST near start of epoch unless absolutely necessary
110 */
111 function IgnoreDaylightSaving(t)
112 {
113 if ((0 <= t && t < msPerYear) && !DST_1970) {
114 return true;
115 }
116 if ((msPerYear <= t && t < 2*msPerYear) && !DST_1971) {
117 return true;
118 }
119 return false;
120 }
122 /*
123 * Date test "ResultArrays" are hard-coded for Pacific Standard Time.
124 * We must adjust them for the tester's own timezone -
125 */
126 function adjustResultArray(ResultArray, msMode)
127 {
128 // If the tester's system clock is in PST, no need to continue -
129 // if (!PST_DIFF) {return;}
131 /* The date testcases instantiate Date objects in two different ways:
132 *
133 * millisecond mode: e.g. dt = new Date(10000000);
134 * year-month-day mode: dt = new Date(2000, 5, 1, ...);
135 *
136 * In the first case, the date is measured from Time 0 in Greenwich (i.e. UTC).
137 * In the second case, it is measured with reference to the tester's local timezone.
138 *
139 * In the first case we must correct those values expected for local measurements,
140 * like dt.getHours() etc. No correction is necessary for dt.getUTCHours() etc.
141 *
142 * In the second case, it is exactly the other way around -
143 */
144 if (msMode)
145 {
146 // The hard-coded UTC milliseconds from Time 0 derives from a UTC date.
147 // Shift to the right by the offset between UTC and the tester.
148 if (IgnoreDaylightSaving(ResultArray[TIME])) {
149 var t = ResultArray[TIME] + TZ_DIFF_RAW*msPerHour;
150 } else {
151 var t = ResultArray[TIME] + TZ_DIFF*msPerHour;
152 }
154 // Use our date arithmetic functions to determine the local hour, day, etc.
155 ResultArray[HOURS] = HourFromTime(t);
156 ResultArray[DAY] = WeekDay(t);
157 ResultArray[DATE] = DateFromTime(t);
158 ResultArray[MONTH] = MonthFromTime(t);
159 ResultArray[YEAR] = YearFromTime(t);
160 }
161 else
162 {
163 // The hard-coded UTC milliseconds from Time 0 derives from a PST date.
164 // Shift to the left by the offset between PST and the tester.
165 var t = ResultArray[TIME] - PST_DIFF*msPerHour;
167 // Use our date arithmetic functions to determine the UTC hour, day, etc.
168 ResultArray[TIME] = t;
169 ResultArray[UTC_HOURS] = HourFromTime(t);
170 ResultArray[UTC_DAY] = WeekDay(t);
171 ResultArray[UTC_DATE] = DateFromTime(t);
172 ResultArray[UTC_MONTH] = MonthFromTime(t);
173 ResultArray[UTC_YEAR] = YearFromTime(t);
174 }
175 }
177 function Day( t ) {
178 return ( Math.floor(t/msPerDay ) );
179 }
180 function DaysInYear( y ) {
181 if ( y % 4 != 0 ) {
182 return 365;
183 }
184 if ( (y % 4 == 0) && (y % 100 != 0) ) {
185 return 366;
186 }
187 if ( (y % 100 == 0) && (y % 400 != 0) ) {
188 return 365;
189 }
190 if ( (y % 400 == 0) ){
191 return 366;
192 } else {
193 return "ERROR: DaysInYear(" + y + ") case not covered";
194 }
195 }
196 function TimeInYear( y ) {
197 return ( DaysInYear(y) * msPerDay );
198 }
199 function DayNumber( t ) {
200 return ( Math.floor( t / msPerDay ) );
201 }
202 function TimeWithinDay( t ) {
204 var r = t % msPerDay;
206 if (r < 0)
207 {
208 r += msPerDay;
209 }
210 return r;
212 }
213 function YearNumber( t ) {
214 }
215 function TimeFromYear( y ) {
216 return ( msPerDay * DayFromYear(y) );
217 }
218 function DayFromYear( y ) {
219 return ( 365*(y-1970) +
220 Math.floor((y-1969)/4) -
221 Math.floor((y-1901)/100) +
222 Math.floor((y-1601)/400) );
223 }
224 function InLeapYear( t ) {
225 if ( DaysInYear(YearFromTime(t)) == 365 ) {
226 return 0;
227 }
228 if ( DaysInYear(YearFromTime(t)) == 366 ) {
229 return 1;
230 } else {
231 return "ERROR: InLeapYear("+ t + ") case not covered";
232 }
233 }
234 function YearFromTime( t ) {
235 t = Number( t );
236 var sign = ( t < 0 ) ? -1 : 1;
237 var year = ( sign < 0 ) ? 1969 : 1970;
238 for ( var timeToTimeZero = t; ; ) {
239 // subtract the current year's time from the time that's left.
240 timeToTimeZero -= sign * TimeInYear(year)
242 // if there's less than the current year's worth of time left, then break.
243 if ( sign < 0 ) {
244 if ( sign * timeToTimeZero <= 0 ) {
245 break;
246 } else {
247 year += sign;
248 }
249 } else {
250 if ( sign * timeToTimeZero < 0 ) {
251 break;
252 } else {
253 year += sign;
254 }
255 }
256 }
257 return ( year );
258 }
259 function MonthFromTime( t ) {
260 // i know i could use switch but i'd rather not until it's part of ECMA
261 var day = DayWithinYear( t );
262 var leap = InLeapYear(t);
264 if ( (0 <= day) && (day < 31) ) {
265 return 0;
266 }
267 if ( (31 <= day) && (day < (59+leap)) ) {
268 return 1;
269 }
270 if ( ((59+leap) <= day) && (day < (90+leap)) ) {
271 return 2;
272 }
273 if ( ((90+leap) <= day) && (day < (120+leap)) ) {
274 return 3;
275 }
276 if ( ((120+leap) <= day) && (day < (151+leap)) ) {
277 return 4;
278 }
279 if ( ((151+leap) <= day) && (day < (181+leap)) ) {
280 return 5;
281 }
282 if ( ((181+leap) <= day) && (day < (212+leap)) ) {
283 return 6;
284 }
285 if ( ((212+leap) <= day) && (day < (243+leap)) ) {
286 return 7;
287 }
288 if ( ((243+leap) <= day) && (day < (273+leap)) ) {
289 return 8;
290 }
291 if ( ((273+leap) <= day) && (day < (304+leap)) ) {
292 return 9;
293 }
294 if ( ((304+leap) <= day) && (day < (334+leap)) ) {
295 return 10;
296 }
297 if ( ((334+leap) <= day) && (day < (365+leap)) ) {
298 return 11;
299 } else {
300 return "ERROR: MonthFromTime("+t+") not known";
301 }
302 }
303 function DayWithinYear( t ) {
304 return( Day(t) - DayFromYear(YearFromTime(t)));
305 }
306 function DateFromTime( t ) {
307 var day = DayWithinYear(t);
308 var month = MonthFromTime(t);
310 if ( month == 0 ) {
311 return ( day + 1 );
312 }
313 if ( month == 1 ) {
314 return ( day - 30 );
315 }
316 if ( month == 2 ) {
317 return ( day - 58 - InLeapYear(t) );
318 }
319 if ( month == 3 ) {
320 return ( day - 89 - InLeapYear(t));
321 }
322 if ( month == 4 ) {
323 return ( day - 119 - InLeapYear(t));
324 }
325 if ( month == 5 ) {
326 return ( day - 150- InLeapYear(t));
327 }
328 if ( month == 6 ) {
329 return ( day - 180- InLeapYear(t));
330 }
331 if ( month == 7 ) {
332 return ( day - 211- InLeapYear(t));
333 }
334 if ( month == 8 ) {
335 return ( day - 242- InLeapYear(t));
336 }
337 if ( month == 9 ) {
338 return ( day - 272- InLeapYear(t));
339 }
340 if ( month == 10 ) {
341 return ( day - 303- InLeapYear(t));
342 }
343 if ( month == 11 ) {
344 return ( day - 333- InLeapYear(t));
345 }
347 return ("ERROR: DateFromTime("+t+") not known" );
348 }
349 function WeekDay( t ) {
350 var weekday = (Day(t)+4) % 7;
351 return( weekday < 0 ? 7 + weekday : weekday );
352 }
354 // missing daylight savings time adjustment
356 function HourFromTime( t ) {
357 var h = Math.floor( t / msPerHour ) % HoursPerDay;
358 return ( (h<0) ? HoursPerDay + h : h );
359 }
360 function MinFromTime( t ) {
361 var min = Math.floor( t / msPerMinute ) % MinutesPerHour;
362 return( ( min < 0 ) ? MinutesPerHour + min : min );
363 }
364 function SecFromTime( t ) {
365 var sec = Math.floor( t / msPerSecond ) % SecondsPerMinute;
366 return ( (sec < 0 ) ? SecondsPerMinute + sec : sec );
367 }
368 function msFromTime( t ) {
369 var ms = t % msPerSecond;
370 return ( (ms < 0 ) ? msPerSecond + ms : ms );
371 }
372 function LocalTZA() {
373 return ( TZ_DIFF_RAW * msPerHour );
374 }
375 function UTC( t ) {
376 return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) );
377 }
378 function LocalTime( t ) {
379 return ( t + LocalTZA() + DaylightSavingTA(t) );
380 }
381 function DaylightSavingTA( t ) {
382 if (IgnoreDaylightSaving(t)) {
383 return 0;
384 }
386 if (DST_PERIOD > 0) {
387 // northern hemisphere
388 var dst_start = GetDSTStart(t);
389 var dst_end = GetDSTEnd(t);
391 if ( t >= dst_start && t < dst_end )
392 return msPerHour;
393 } else if (DST_PERIOD < 0) {
394 // southern hemisphere
395 var dst_start = GetDSTStart_Southern(t);
396 var dst_end = GetDSTEnd_Southern(t);
398 if ( t >= dst_start && t < GetDSTEnd_Southern(t + msPerYear) )
399 return msPerHour;
400 if ( t < dst_end && t >= GetDSTEnd_Southern(t - msPerYear) )
401 return msPerHour;
402 }
404 return 0;
405 }
407 function GetFirstSundayInMonth( t, m ) {
408 var year = YearFromTime(t);
409 var leap = InLeapYear(t);
411 // month m 0..11
412 // april == 3
413 // march == 2
415 // set time to first day of month m
416 var time = TimeFromYear(year);
417 for (var i = 0; i < m; ++i)
418 {
419 time += TimeInMonth(i, leap);
420 }
422 for ( var first_sunday = time; WeekDay(first_sunday) > 0;
423 first_sunday += msPerDay )
424 {
425 ;
426 }
428 return first_sunday;
429 }
431 function GetLastSundayInMonth( t, m ) {
432 var year = YearFromTime(t);
433 var leap = InLeapYear(t);
435 // month m 0..11
436 // april == 3
437 // march == 2
439 // first day of following month
440 var time = TimeFromYear(year);
441 for (var i = 0; i <= m; ++i)
442 {
443 time += TimeInMonth(i, leap);
444 }
445 // prev day == last day of month
446 time -= msPerDay;
448 for ( var last_sunday = time; WeekDay(last_sunday) > 0;
449 last_sunday -= msPerDay )
450 {
451 ;
452 }
453 return last_sunday;
454 }
456 /*
457 15.9.1.9 Daylight Saving Time Adjustment
459 The implementation of ECMAScript should not try to determine whether
460 the exact time was subject to daylight saving time, but just whether
461 daylight saving time would have been in effect if the current
462 daylight saving time algorithm had been used at the time. This avoids
463 complications such as taking into account the years that the locale
464 observed daylight saving time year round.
465 */
467 /*
468 US DST algorithm
470 Before 2007, DST starts first Sunday in April at 2 AM and ends last
471 Sunday in October at 2 AM
473 Starting in 2007, DST starts second Sunday in March at 2 AM and ends
474 first Sunday in November at 2 AM
476 Note that different operating systems behave differently.
478 Fully patched Windows XP uses the 2007 algorithm for all dates while
479 fully patched Fedora Core 6 and RHEL 4 Linux use the algorithm in
480 effect at the time.
482 Since pre-2007 DST is a subset of 2007 DST rules, this only affects
483 tests that occur in the period Mar-Apr and Oct-Nov where the two
484 algorithms do not agree.
486 */
488 function GetDSTStart( t )
489 {
490 return (GetFirstSundayInMonth(t, 2) + 7*msPerDay + 2*msPerHour - LocalTZA());
491 }
493 function GetDSTEnd( t )
494 {
495 return (GetFirstSundayInMonth(t, 10) + 2*msPerHour - LocalTZA());
496 }
498 function GetOldDSTStart( t )
499 {
500 return (GetFirstSundayInMonth(t, 3) + 2*msPerHour - LocalTZA());
501 }
503 function GetOldDSTEnd( t )
504 {
505 return (GetLastSundayInMonth(t, 9) + 2*msPerHour - LocalTZA());
506 }
508 /*
509 * Daylight saving time start/end date for 'Australia'
510 * (arbitrarily chosen as a representative for the southern hemisphere)
511 */
513 function GetDSTStart_Southern( t )
514 {
515 return (GetFirstSundayInMonth(t, 9) + 2*msPerHour - LocalTZA());
516 }
518 function GetDSTEnd_Southern( t )
519 {
520 return (GetFirstSundayInMonth(t, 3) + 2*msPerHour - LocalTZA());
521 }
523 function MakeTime( hour, min, sec, ms ) {
524 if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) {
525 return Number.NaN;
526 }
528 hour = ToInteger(hour);
529 min = ToInteger( min);
530 sec = ToInteger( sec);
531 ms = ToInteger( ms );
533 return( (hour*msPerHour) + (min*msPerMinute) +
534 (sec*msPerSecond) + ms );
535 }
536 function MakeDay( year, month, date ) {
537 if ( isNaN(year) || isNaN(month) || isNaN(date) ) {
538 return Number.NaN;
539 }
540 year = ToInteger(year);
541 month = ToInteger(month);
542 date = ToInteger(date );
544 var sign = ( year < 1970 ) ? -1 : 1;
545 var t = ( year < 1970 ) ? 1 : 0;
546 var y = ( year < 1970 ) ? 1969 : 1970;
548 var result5 = year + Math.floor( month/12 );
549 var result6 = month % 12;
551 if ( year < 1970 ) {
552 for ( y = 1969; y >= year; y += sign ) {
553 t += sign * TimeInYear(y);
554 }
555 } else {
556 for ( y = 1970 ; y < year; y += sign ) {
557 t += sign * TimeInYear(y);
558 }
559 }
561 var leap = InLeapYear( t );
563 for ( var m = 0; m < month; m++ ) {
564 t += TimeInMonth( m, leap );
565 }
567 if ( YearFromTime(t) != result5 ) {
568 return Number.NaN;
569 }
570 if ( MonthFromTime(t) != result6 ) {
571 return Number.NaN;
572 }
573 if ( DateFromTime(t) != 1 ) {
574 return Number.NaN;
575 }
577 return ( (Day(t)) + date - 1 );
578 }
579 function TimeInMonth( month, leap ) {
580 // september april june november
581 // jan 0 feb 1 mar 2 apr 3 may 4 june 5 jul 6
582 // aug 7 sep 8 oct 9 nov 10 dec 11
584 if ( month == 3 || month == 5 || month == 8 || month == 10 ) {
585 return ( 30*msPerDay );
586 }
588 // all the rest
589 if ( month == 0 || month == 2 || month == 4 || month == 6 ||
590 month == 7 || month == 9 || month == 11 ) {
591 return ( 31*msPerDay );
592 }
594 // save february
595 return ( (leap == 0) ? 28*msPerDay : 29*msPerDay );
596 }
597 function MakeDate( day, time ) {
598 if ( day == Number.POSITIVE_INFINITY ||
599 day == Number.NEGATIVE_INFINITY ) {
600 return Number.NaN;
601 }
602 if ( time == Number.POSITIVE_INFINITY ||
603 time == Number.NEGATIVE_INFINITY ) {
604 return Number.NaN;
605 }
606 return ( day * msPerDay ) + time;
607 }
608 function TimeClip( t ) {
609 if ( isNaN( t ) ) {
610 return ( Number.NaN );
611 }
612 if ( Math.abs( t ) > 8.64e15 ) {
613 return ( Number.NaN );
614 }
616 return ( ToInteger( t ) );
617 }
618 function ToInteger( t ) {
619 t = Number( t );
621 if ( isNaN( t ) ){
622 return ( Number.NaN );
623 }
624 if ( t == 0 || t == -0 ||
625 t == Number.POSITIVE_INFINITY || t == Number.NEGATIVE_INFINITY ) {
626 return 0;
627 }
629 var sign = ( t < 0 ) ? -1 : 1;
631 return ( sign * Math.floor( Math.abs( t ) ) );
632 }
633 function Enumerate ( o ) {
634 var p;
635 for ( p in o ) {
636 print( p +": " + o[p] );
637 }
638 }
640 /* these functions are useful for running tests manually in Rhino */
642 function GetContext() {
643 return Packages.com.netscape.javascript.Context.getCurrentContext();
644 }
645 function OptLevel( i ) {
646 i = Number(i);
647 var cx = GetContext();
648 cx.setOptimizationLevel(i);
649 }
650 /* end of Rhino functions */