]>
Commit | Line | Data |
---|---|---|
b37bf2e1 A |
1 | /* The contents of this file are subject to the Netscape Public |
2 | * License Version 1.1 (the "License"); you may not use this file | |
3 | * except in compliance with the License. You may obtain a copy of | |
4 | * the License at http://www.mozilla.org/NPL/ | |
5 | * | |
6 | * Software distributed under the License is distributed on an "AS | |
7 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
8 | * implied. See the License for the specific language governing | |
9 | * rights and limitations under the License. | |
10 | * | |
11 | * The Original Code is Mozilla Communicator client code, released March | |
12 | * 31, 1998. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Netscape Communications | |
15 | * Corporation. Portions created by Netscape are | |
16 | * Copyright (C) 1998 Netscape Communications Corporation. All | |
17 | * Rights Reserved. | |
18 | * | |
19 | * Contributor(s): | |
20 | * | |
21 | */ | |
22 | /* | |
23 | * JavaScript shared functions file for running the tests in either | |
24 | * stand-alone JavaScript engine. To run a test, first load this file, | |
25 | * then load the test script. | |
26 | */ | |
27 | ||
28 | var completed = false; | |
29 | var testcases; | |
30 | var tc = 0; | |
31 | ||
32 | SECTION = ""; | |
33 | VERSION = ""; | |
34 | BUGNUMBER = ""; | |
35 | ||
36 | /* | |
37 | * constant strings | |
38 | */ | |
39 | var GLOBAL = "[object global]"; | |
40 | var PASSED = " PASSED!" | |
41 | var FAILED = " FAILED! expected: "; | |
42 | ||
43 | var DEBUG = false; | |
44 | ||
45 | ||
46 | ||
47 | /* wrapper for test cas constructor that doesn't require the SECTION | |
48 | * argument. | |
49 | */ | |
50 | ||
51 | function AddTestCase( description, expect, actual ) { | |
52 | testcases[tc++] = new TestCase( SECTION, description, expect, actual ); | |
53 | } | |
54 | ||
55 | /* | |
56 | * TestCase constructor | |
57 | * | |
58 | */ | |
59 | ||
60 | function TestCase( n, d, e, a ) { | |
61 | this.name = n; | |
62 | this.description = d; | |
63 | this.expect = e; | |
64 | this.actual = a; | |
65 | this.passed = true; | |
66 | this.reason = ""; | |
67 | this.bugnumber = BUGNUMBER; | |
68 | ||
69 | this.passed = getTestCaseResult( this.expect, this.actual ); | |
70 | if ( DEBUG ) { | |
71 | writeLineToLog( "added " + this.description ); | |
72 | } | |
73 | } | |
74 | ||
75 | /* | |
76 | * Set up test environment. | |
77 | * | |
78 | */ | |
79 | function startTest() { | |
80 | if ( version ) { | |
81 | // JavaScript 1.3 is supposed to be compliant ecma version 1.0 | |
82 | if ( VERSION == "ECMA_1" ) { | |
83 | version ( "130" ); | |
84 | } | |
85 | if ( VERSION == "JS_1.3" ) { | |
86 | version ( "130" ); | |
87 | } | |
88 | if ( VERSION == "JS_1.2" ) { | |
89 | version ( "120" ); | |
90 | } | |
91 | if ( VERSION == "JS_1.1" ) { | |
92 | version ( "110" ); | |
93 | } | |
94 | // for ecma version 2.0, we will leave the javascript version to | |
95 | // the default ( for now ). | |
96 | } | |
97 | ||
98 | // print out bugnumber | |
99 | ||
100 | if ( BUGNUMBER ) { | |
101 | writeLineToLog ("BUGNUMBER: " + BUGNUMBER ); | |
102 | } | |
103 | ||
104 | testcases = new Array(); | |
105 | tc = 0; | |
106 | } | |
107 | ||
108 | ||
109 | function test() { | |
110 | for ( tc=0; tc < testcases.length; tc++ ) { | |
111 | testcases[tc].passed = writeTestCaseResult( | |
112 | testcases[tc].expect, | |
113 | testcases[tc].actual, | |
114 | testcases[tc].description +" = "+ testcases[tc].actual ); | |
115 | testcases[tc].reason += ( testcases[tc].passed ) ? "" : "wrong value "; | |
116 | } | |
117 | stopTest(); | |
118 | return ( testcases ); | |
119 | } | |
120 | ||
121 | /* | |
122 | * Compare expected result to the actual result and figure out whether | |
123 | * the test case passed. | |
124 | */ | |
125 | function getTestCaseResult( expect, actual ) { | |
126 | // because ( NaN == NaN ) always returns false, need to do | |
127 | // a special compare to see if we got the right result. | |
128 | if ( actual != actual ) { | |
129 | if ( typeof actual == "object" ) { | |
130 | actual = "NaN object"; | |
131 | } else { | |
132 | actual = "NaN number"; | |
133 | } | |
134 | } | |
135 | if ( expect != expect ) { | |
136 | if ( typeof expect == "object" ) { | |
137 | expect = "NaN object"; | |
138 | } else { | |
139 | expect = "NaN number"; | |
140 | } | |
141 | } | |
142 | ||
143 | var passed = ( expect == actual ) ? true : false; | |
144 | ||
145 | // if both objects are numbers | |
146 | // need to replace w/ IEEE standard for rounding | |
147 | if ( !passed | |
148 | && typeof(actual) == "number" | |
149 | && typeof(expect) == "number" | |
150 | ) { | |
151 | if ( Math.abs(actual-expect) < 0.0000001 ) { | |
152 | passed = true; | |
153 | } | |
154 | } | |
155 | ||
156 | // verify type is the same | |
157 | if ( typeof(expect) != typeof(actual) ) { | |
158 | passed = false; | |
159 | } | |
160 | ||
161 | return passed; | |
162 | } | |
163 | ||
164 | /* | |
165 | * Begin printing functions. These functions use the shell's | |
166 | * print function. When running tests in the browser, these | |
167 | * functions, override these functions with functions that use | |
168 | * document.write. | |
169 | */ | |
170 | ||
171 | function writeTestCaseResult( expect, actual, string ) { | |
172 | var passed = getTestCaseResult( expect, actual ); | |
173 | writeFormattedResult( expect, actual, string, passed ); | |
174 | return passed; | |
175 | } | |
176 | function writeFormattedResult( expect, actual, string, passed ) { | |
177 | var s = string ; | |
178 | s += ( passed ) ? PASSED : FAILED + expect; | |
179 | writeLineToLog( s); | |
180 | return passed; | |
181 | } | |
182 | function writeLineToLog( string ) { | |
183 | print( string ); | |
184 | } | |
185 | function writeHeaderToLog( string ) { | |
186 | print( string ); | |
187 | } | |
188 | /* end of print functions */ | |
189 | ||
190 | ||
191 | /* | |
192 | * When running in the shell, run the garbage collector after the | |
193 | * test has completed. | |
194 | */ | |
195 | ||
196 | function stopTest() { | |
197 | var gc; | |
198 | if ( gc != undefined ) { | |
199 | gc(); | |
200 | } | |
201 | } | |
202 | ||
203 | /* | |
204 | * Convenience function for displaying failed test cases. Useful | |
205 | * when running tests manually. | |
206 | * | |
207 | */ | |
208 | function getFailedCases() { | |
209 | for ( var i = 0; i < testcases.length; i++ ) { | |
210 | if ( ! testcases[i].passed ) { | |
211 | print( testcases[i].description +" = " +testcases[i].actual +" expected: "+ testcases[i].expect ); | |
212 | } | |
213 | } | |
214 | } | |
215 | /* | |
216 | * Date functions used by tests in Date suite | |
217 | * | |
218 | */ | |
219 | var msPerDay = 86400000; | |
220 | var HoursPerDay = 24; | |
221 | var MinutesPerHour = 60; | |
222 | var SecondsPerMinute = 60; | |
223 | var msPerSecond = 1000; | |
224 | var msPerMinute = 60000; // msPerSecond * SecondsPerMinute | |
225 | var msPerHour = 3600000; // msPerMinute * MinutesPerHour | |
226 | var TZ_DIFF = getTimeZoneDiff(); // offset of tester's timezone from UTC | |
227 | var TZ_PST = -8; // offset of Pacific Standard Time from UTC | |
228 | var PST_DIFF = TZ_DIFF - TZ_PST; // offset of tester's timezone from PST | |
229 | var TIME_1970 = 0; | |
230 | var TIME_2000 = 946684800000; | |
231 | var TIME_1900 = -2208988800000; | |
232 | var TIME_YEAR_0 = -62167219200000; | |
233 | ||
234 | ||
235 | /* | |
236 | * Originally, the test suite used a hard-coded value TZ_DIFF = -8. | |
237 | * But that was only valid for testers in the Pacific Standard Time Zone! | |
238 | * We calculate the proper number dynamically for any tester. We just | |
239 | * have to be careful not to use a date subject to Daylight Savings Time... | |
240 | */ | |
241 | function getTimeZoneDiff() | |
242 | { | |
243 | return -((new Date(2000, 1, 1)).getTimezoneOffset())/60; | |
244 | } | |
245 | ||
246 | ||
247 | /* | |
248 | * Date test "ResultArrays" are hard-coded for Pacific Standard Time. | |
249 | * We must adjust them for the tester's own timezone - | |
250 | */ | |
251 | function adjustResultArray(ResultArray, msMode) | |
252 | { | |
253 | // If the tester's system clock is in PST, no need to continue - | |
254 | if (!PST_DIFF) {return;} | |
255 | ||
256 | /* The date testcases instantiate Date objects in two different ways: | |
257 | * | |
258 | * millisecond mode: e.g. dt = new Date(10000000); | |
259 | * year-month-day mode: dt = new Date(2000, 5, 1, ...); | |
260 | * | |
261 | * In the first case, the date is measured from Time 0 in Greenwich (i.e. UTC). | |
262 | * In the second case, it is measured with reference to the tester's local timezone. | |
263 | * | |
264 | * In the first case we must correct those values expected for local measurements, | |
265 | * like dt.getHours() etc. No correction is necessary for dt.getUTCHours() etc. | |
266 | * | |
267 | * In the second case, it is exactly the other way around - | |
268 | */ | |
269 | if (msMode) | |
270 | { | |
271 | // The hard-coded UTC milliseconds from Time 0 derives from a UTC date. | |
272 | // Shift to the right by the offset between UTC and the tester. | |
273 | var t = ResultArray[TIME] + TZ_DIFF*msPerHour; | |
274 | ||
275 | // Use our date arithmetic functions to determine the local hour, day, etc. | |
276 | ResultArray[HOURS] = HourFromTime(t); | |
277 | ResultArray[DAY] = WeekDay(t); | |
278 | ResultArray[DATE] = DateFromTime(t); | |
279 | ResultArray[MONTH] = MonthFromTime(t); | |
280 | ResultArray[YEAR] = YearFromTime(t); | |
281 | } | |
282 | else | |
283 | { | |
284 | // The hard-coded UTC milliseconds from Time 0 derives from a PST date. | |
285 | // Shift to the left by the offset between PST and the tester. | |
286 | var t = ResultArray[TIME] - PST_DIFF*msPerHour; | |
287 | ||
288 | // Use our date arithmetic functions to determine the UTC hour, day, etc. | |
289 | ResultArray[TIME] = t; | |
290 | ResultArray[UTC_HOURS] = HourFromTime(t); | |
291 | ResultArray[UTC_DAY] = WeekDay(t); | |
292 | ResultArray[UTC_DATE] = DateFromTime(t); | |
293 | ResultArray[UTC_MONTH] = MonthFromTime(t); | |
294 | ResultArray[UTC_YEAR] = YearFromTime(t); | |
295 | } | |
296 | } | |
297 | ||
298 | ||
299 | function Day( t ) { | |
300 | return ( Math.floor(t/msPerDay ) ); | |
301 | } | |
302 | function DaysInYear( y ) { | |
303 | if ( y % 4 != 0 ) { | |
304 | return 365; | |
305 | } | |
306 | if ( (y % 4 == 0) && (y % 100 != 0) ) { | |
307 | return 366; | |
308 | } | |
309 | if ( (y % 100 == 0) && (y % 400 != 0) ) { | |
310 | return 365; | |
311 | } | |
312 | if ( (y % 400 == 0) ){ | |
313 | return 366; | |
314 | } else { | |
315 | return "ERROR: DaysInYear(" + y + ") case not covered"; | |
316 | } | |
317 | } | |
318 | function TimeInYear( y ) { | |
319 | return ( DaysInYear(y) * msPerDay ); | |
320 | } | |
321 | function DayNumber( t ) { | |
322 | return ( Math.floor( t / msPerDay ) ); | |
323 | } | |
324 | function TimeWithinDay( t ) { | |
325 | if ( t < 0 ) { | |
326 | return ( (t % msPerDay) + msPerDay ); | |
327 | } else { | |
328 | return ( t % msPerDay ); | |
329 | } | |
330 | } | |
331 | function YearNumber( t ) { | |
332 | } | |
333 | function TimeFromYear( y ) { | |
334 | return ( msPerDay * DayFromYear(y) ); | |
335 | } | |
336 | function DayFromYear( y ) { | |
337 | return ( 365*(y-1970) + | |
338 | Math.floor((y-1969)/4) - | |
339 | Math.floor((y-1901)/100) + | |
340 | Math.floor((y-1601)/400) ); | |
341 | } | |
342 | function InLeapYear( t ) { | |
343 | if ( DaysInYear(YearFromTime(t)) == 365 ) { | |
344 | return 0; | |
345 | } | |
346 | if ( DaysInYear(YearFromTime(t)) == 366 ) { | |
347 | return 1; | |
348 | } else { | |
349 | return "ERROR: InLeapYear("+ t + ") case not covered"; | |
350 | } | |
351 | } | |
352 | function YearFromTime( t ) { | |
353 | t = Number( t ); | |
354 | var sign = ( t < 0 ) ? -1 : 1; | |
355 | var year = ( sign < 0 ) ? 1969 : 1970; | |
356 | for ( var timeToTimeZero = t; ; ) { | |
357 | // subtract the current year's time from the time that's left. | |
358 | timeToTimeZero -= sign * TimeInYear(year) | |
359 | ||
360 | // if there's less than the current year's worth of time left, then break. | |
361 | if ( sign < 0 ) { | |
362 | if ( sign * timeToTimeZero <= 0 ) { | |
363 | break; | |
364 | } else { | |
365 | year += sign; | |
366 | } | |
367 | } else { | |
368 | if ( sign * timeToTimeZero < 0 ) { | |
369 | break; | |
370 | } else { | |
371 | year += sign; | |
372 | } | |
373 | } | |
374 | } | |
375 | return ( year ); | |
376 | } | |
377 | function MonthFromTime( t ) { | |
378 | // i know i could use switch but i'd rather not until it's part of ECMA | |
379 | var day = DayWithinYear( t ); | |
380 | var leap = InLeapYear(t); | |
381 | ||
382 | if ( (0 <= day) && (day < 31) ) { | |
383 | return 0; | |
384 | } | |
385 | if ( (31 <= day) && (day < (59+leap)) ) { | |
386 | return 1; | |
387 | } | |
388 | if ( ((59+leap) <= day) && (day < (90+leap)) ) { | |
389 | return 2; | |
390 | } | |
391 | if ( ((90+leap) <= day) && (day < (120+leap)) ) { | |
392 | return 3; | |
393 | } | |
394 | if ( ((120+leap) <= day) && (day < (151+leap)) ) { | |
395 | return 4; | |
396 | } | |
397 | if ( ((151+leap) <= day) && (day < (181+leap)) ) { | |
398 | return 5; | |
399 | } | |
400 | if ( ((181+leap) <= day) && (day < (212+leap)) ) { | |
401 | return 6; | |
402 | } | |
403 | if ( ((212+leap) <= day) && (day < (243+leap)) ) { | |
404 | return 7; | |
405 | } | |
406 | if ( ((243+leap) <= day) && (day < (273+leap)) ) { | |
407 | return 8; | |
408 | } | |
409 | if ( ((273+leap) <= day) && (day < (304+leap)) ) { | |
410 | return 9; | |
411 | } | |
412 | if ( ((304+leap) <= day) && (day < (334+leap)) ) { | |
413 | return 10; | |
414 | } | |
415 | if ( ((334+leap) <= day) && (day < (365+leap)) ) { | |
416 | return 11; | |
417 | } else { | |
418 | return "ERROR: MonthFromTime("+t+") not known"; | |
419 | } | |
420 | } | |
421 | function DayWithinYear( t ) { | |
422 | return( Day(t) - DayFromYear(YearFromTime(t))); | |
423 | } | |
424 | function DateFromTime( t ) { | |
425 | var day = DayWithinYear(t); | |
426 | var month = MonthFromTime(t); | |
427 | ||
428 | if ( month == 0 ) { | |
429 | return ( day + 1 ); | |
430 | } | |
431 | if ( month == 1 ) { | |
432 | return ( day - 30 ); | |
433 | } | |
434 | if ( month == 2 ) { | |
435 | return ( day - 58 - InLeapYear(t) ); | |
436 | } | |
437 | if ( month == 3 ) { | |
438 | return ( day - 89 - InLeapYear(t)); | |
439 | } | |
440 | if ( month == 4 ) { | |
441 | return ( day - 119 - InLeapYear(t)); | |
442 | } | |
443 | if ( month == 5 ) { | |
444 | return ( day - 150- InLeapYear(t)); | |
445 | } | |
446 | if ( month == 6 ) { | |
447 | return ( day - 180- InLeapYear(t)); | |
448 | } | |
449 | if ( month == 7 ) { | |
450 | return ( day - 211- InLeapYear(t)); | |
451 | } | |
452 | if ( month == 8 ) { | |
453 | return ( day - 242- InLeapYear(t)); | |
454 | } | |
455 | if ( month == 9 ) { | |
456 | return ( day - 272- InLeapYear(t)); | |
457 | } | |
458 | if ( month == 10 ) { | |
459 | return ( day - 303- InLeapYear(t)); | |
460 | } | |
461 | if ( month == 11 ) { | |
462 | return ( day - 333- InLeapYear(t)); | |
463 | } | |
464 | ||
465 | return ("ERROR: DateFromTime("+t+") not known" ); | |
466 | } | |
467 | function WeekDay( t ) { | |
468 | var weekday = (Day(t)+4) % 7; | |
469 | return( weekday < 0 ? 7 + weekday : weekday ); | |
470 | } | |
471 | ||
472 | // missing daylight savins time adjustment | |
473 | ||
474 | function HourFromTime( t ) { | |
475 | var h = Math.floor( t / msPerHour ) % HoursPerDay; | |
476 | return ( (h<0) ? HoursPerDay + h : h ); | |
477 | } | |
478 | function MinFromTime( t ) { | |
479 | var min = Math.floor( t / msPerMinute ) % MinutesPerHour; | |
480 | return( ( min < 0 ) ? MinutesPerHour + min : min ); | |
481 | } | |
482 | function SecFromTime( t ) { | |
483 | var sec = Math.floor( t / msPerSecond ) % SecondsPerMinute; | |
484 | return ( (sec < 0 ) ? SecondsPerMinute + sec : sec ); | |
485 | } | |
486 | function msFromTime( t ) { | |
487 | var ms = t % msPerSecond; | |
488 | return ( (ms < 0 ) ? msPerSecond + ms : ms ); | |
489 | } | |
490 | function LocalTZA() { | |
491 | return ( TZ_DIFF * msPerHour ); | |
492 | } | |
493 | function UTC( t ) { | |
494 | return ( t - LocalTZA() - DaylightSavingTA(t - LocalTZA()) ); | |
495 | } | |
496 | ||
497 | function DaylightSavingTA( t ) { | |
498 | t = t - LocalTZA(); | |
499 | ||
500 | var dst_start = GetSecondSundayInMarch(t) + 2*msPerHour; | |
501 | var dst_end = GetFirstSundayInNovember(t)+ 2*msPerHour; | |
502 | ||
503 | if ( t >= dst_start && t < dst_end ) { | |
504 | return msPerHour; | |
505 | } else { | |
506 | return 0; | |
507 | } | |
508 | ||
509 | // Daylight Savings Time starts on the first Sunday in April at 2:00AM in | |
510 | // PST. Other time zones will need to override this function. | |
511 | ||
512 | print( new Date( UTC(dst_start + LocalTZA())) ); | |
513 | ||
514 | return UTC(dst_start + LocalTZA()); | |
515 | } | |
516 | ||
517 | function GetFirstSundayInApril( t ) { | |
518 | var year = YearFromTime(t); | |
519 | var leap = InLeapYear(t); | |
520 | ||
521 | var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) + | |
522 | TimeInMonth(2,leap); | |
523 | ||
524 | for ( var first_sunday = april; WeekDay(first_sunday) > 0; | |
525 | first_sunday += msPerDay ) | |
526 | { | |
527 | ; | |
528 | } | |
529 | ||
530 | return first_sunday; | |
531 | } | |
532 | function GetLastSundayInOctober( t ) { | |
533 | var year = YearFromTime(t); | |
534 | var leap = InLeapYear(t); | |
535 | ||
536 | for ( var oct = TimeFromYear(year), m = 0; m < 9; m++ ) { | |
537 | oct += TimeInMonth(m, leap); | |
538 | } | |
539 | for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0; | |
540 | last_sunday -= msPerDay ) | |
541 | { | |
542 | ; | |
543 | } | |
544 | return last_sunday; | |
545 | } | |
546 | ||
547 | // Added these two functions because DST rules changed for the US. | |
548 | function GetSecondSundayInMarch( t ) { | |
549 | var year = YearFromTime(t); | |
550 | var leap = InLeapYear(t); | |
551 | ||
552 | var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap); | |
553 | ||
554 | var sundayCount = 0; | |
555 | var flag = true; | |
556 | for ( var second_sunday = march; flag; second_sunday += msPerDay ) | |
557 | { | |
558 | if (WeekDay(second_sunday) == 0) { | |
559 | if(++sundayCount == 2) | |
560 | flag = false; | |
561 | } | |
562 | } | |
563 | ||
564 | return second_sunday; | |
565 | } | |
566 | function GetFirstSundayInNovember( t ) { | |
567 | var year = YearFromTime(t); | |
568 | var leap = InLeapYear(t); | |
569 | ||
570 | for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) { | |
571 | nov += TimeInMonth(m, leap); | |
572 | } | |
573 | for ( var first_sunday = nov; WeekDay(first_sunday) > 0; | |
574 | first_sunday += msPerDay ) | |
575 | { | |
576 | ; | |
577 | } | |
578 | return first_sunday; | |
579 | } | |
580 | function LocalTime( t ) { | |
581 | return ( t + LocalTZA() + DaylightSavingTA(t) ); | |
582 | } | |
583 | function MakeTime( hour, min, sec, ms ) { | |
584 | if ( isNaN( hour ) || isNaN( min ) || isNaN( sec ) || isNaN( ms ) ) { | |
585 | return Number.NaN; | |
586 | } | |
587 | ||
588 | hour = ToInteger(hour); | |
589 | min = ToInteger( min); | |
590 | sec = ToInteger( sec); | |
591 | ms = ToInteger( ms ); | |
592 | ||
593 | return( (hour*msPerHour) + (min*msPerMinute) + | |
594 | (sec*msPerSecond) + ms ); | |
595 | } | |
596 | function MakeDay( year, month, date ) { | |
597 | if ( isNaN(year) || isNaN(month) || isNaN(date) ) { | |
598 | return Number.NaN; | |
599 | } | |
600 | year = ToInteger(year); | |
601 | month = ToInteger(month); | |
602 | date = ToInteger(date ); | |
603 | ||
604 | var sign = ( year < 1970 ) ? -1 : 1; | |
605 | var t = ( year < 1970 ) ? 1 : 0; | |
606 | var y = ( year < 1970 ) ? 1969 : 1970; | |
607 | ||
608 | var result5 = year + Math.floor( month/12 ); | |
609 | var result6 = month % 12; | |
610 | ||
611 | if ( year < 1970 ) { | |
612 | for ( y = 1969; y >= year; y += sign ) { | |
613 | t += sign * TimeInYear(y); | |
614 | } | |
615 | } else { | |
616 | for ( y = 1970 ; y < year; y += sign ) { | |
617 | t += sign * TimeInYear(y); | |
618 | } | |
619 | } | |
620 | ||
621 | var leap = InLeapYear( t ); | |
622 | ||
623 | for ( var m = 0; m < month; m++ ) { | |
624 | t += TimeInMonth( m, leap ); | |
625 | } | |
626 | ||
627 | if ( YearFromTime(t) != result5 ) { | |
628 | return Number.NaN; | |
629 | } | |
630 | if ( MonthFromTime(t) != result6 ) { | |
631 | return Number.NaN; | |
632 | } | |
633 | if ( DateFromTime(t) != 1 ) { | |
634 | return Number.NaN; | |
635 | } | |
636 | ||
637 | return ( (Day(t)) + date - 1 ); | |
638 | } | |
639 | function TimeInMonth( month, leap ) { | |
640 | // september april june november | |
641 | // jan 0 feb 1 mar 2 apr 3 may 4 june 5 jul 6 | |
642 | // aug 7 sep 8 oct 9 nov 10 dec 11 | |
643 | ||
644 | if ( month == 3 || month == 5 || month == 8 || month == 10 ) { | |
645 | return ( 30*msPerDay ); | |
646 | } | |
647 | ||
648 | // all the rest | |
649 | if ( month == 0 || month == 2 || month == 4 || month == 6 || | |
650 | month == 7 || month == 9 || month == 11 ) { | |
651 | return ( 31*msPerDay ); | |
652 | } | |
653 | ||
654 | // save february | |
655 | return ( (leap == 0) ? 28*msPerDay : 29*msPerDay ); | |
656 | } | |
657 | function MakeDate( day, time ) { | |
658 | if ( day == Number.POSITIVE_INFINITY || | |
659 | day == Number.NEGATIVE_INFINITY || | |
660 | day == Number.NaN ) { | |
661 | return Number.NaN; | |
662 | } | |
663 | if ( time == Number.POSITIVE_INFINITY || | |
664 | time == Number.POSITIVE_INFINITY || | |
665 | day == Number.NaN) { | |
666 | return Number.NaN; | |
667 | } | |
668 | return ( day * msPerDay ) + time; | |
669 | } | |
670 | function TimeClip( t ) { | |
671 | if ( isNaN( t ) ) { | |
672 | return ( Number.NaN ); | |
673 | } | |
674 | if ( Math.abs( t ) > 8.64e15 ) { | |
675 | return ( Number.NaN ); | |
676 | } | |
677 | ||
678 | return ( ToInteger( t ) ); | |
679 | } | |
680 | function ToInteger( t ) { | |
681 | t = Number( t ); | |
682 | ||
683 | if ( isNaN( t ) ){ | |
684 | return ( Number.NaN ); | |
685 | } | |
686 | if ( t == 0 || t == -0 || | |
687 | t == Number.POSITIVE_INFINITY || t == Number.NEGATIVE_INFINITY ) { | |
688 | return 0; | |
689 | } | |
690 | ||
691 | var sign = ( t < 0 ) ? -1 : 1; | |
692 | ||
693 | return ( sign * Math.floor( Math.abs( t ) ) ); | |
694 | } | |
695 | function Enumerate ( o ) { | |
696 | var p; | |
697 | for ( p in o ) { | |
698 | print( p +": " + o[p] ); | |
699 | } | |
700 | } | |
701 | ||
702 | /* these functions are useful for running tests manually in Rhino */ | |
703 | ||
704 | function GetContext() { | |
705 | return Packages.com.netscape.javascript.Context.getCurrentContext(); | |
706 | } | |
707 | function OptLevel( i ) { | |
708 | i = Number(i); | |
709 | var cx = GetContext(); | |
710 | cx.setOptimizationLevel(i); | |
711 | } | |
712 | /* end of Rhino functions */ |