root/releases/elgg0.8rc2/lib/adodb/adodb-time.inc.php

Revision 725, 38.9 kB (checked in by misja, 2 years ago)

Updated ADODB library.

  • Property svn:eol-style set to native
Line 
1 <?php
2 /**
3 ADOdb Date Library, part of the ADOdb abstraction library
4 Download: http://phplens.com/phpeverywhere/
5
6 PHP native date functions use integer timestamps for computations.
7 Because of this, dates are restricted to the years 1901-2038 on Unix
8 and 1970-2038 on Windows due to integer overflow for dates beyond
9 those years. This library overcomes these limitations by replacing the
10 native function's signed integers (normally 32-bits) with PHP floating
11 point numbers (normally 64-bits).
12
13 Dates from 100 A.D. to 3000 A.D. and later
14 have been tested. The minimum is 100 A.D. as <100 will invoke the
15 2 => 4 digit year conversion. The maximum is billions of years in the
16 future, but this is a theoretical limit as the computation of that year
17 would take too long with the current implementation of adodb_mktime().
18
19 This library replaces native functions as follows:
20
21 <pre>   
22     getdate()  with  adodb_getdate()
23     date()     with  adodb_date()
24     gmdate()   with  adodb_gmdate()
25     mktime()   with  adodb_mktime()
26     gmmktime() with  adodb_gmmktime()
27     strftime() with  adodb_strftime()
28     strftime() with  adodb_gmstrftime()
29 </pre>
30     
31 The parameters are identical, except that adodb_date() accepts a subset
32 of date()'s field formats. Mktime() will convert from local time to GMT,
33 and date() will convert from GMT to local time, but daylight savings is
34 not handled currently.
35
36 This library is independant of the rest of ADOdb, and can be used
37 as standalone code.
38
39 PERFORMANCE
40
41 For high speed, this library uses the native date functions where
42 possible, and only switches to PHP code when the dates fall outside
43 the 32-bit signed integer range.
44
45 GREGORIAN CORRECTION
46
47 Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
48 October 4, 1582 (Julian) was followed immediately by Friday, October 15,
49 1582 (Gregorian).
50
51 Since 0.06, we handle this correctly, so:
52
53 adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
54     == 24 * 3600 (1 day)
55
56 =============================================================================
57
58 COPYRIGHT
59
60 (c) 2003-2005 John Lim and released under BSD-style license except for code by
61 jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
62 and originally found at http://www.php.net/manual/en/function.mktime.php
63
64 =============================================================================
65
66 BUG REPORTS
67
68 These should be posted to the ADOdb forums at
69
70     http://phplens.com/lens/lensforum/topics.php?id=4
71
72 =============================================================================
73
74 FUNCTION DESCRIPTIONS
75
76
77 ** FUNCTION adodb_getdate($date=false)
78
79 Returns an array containing date information, as getdate(), but supports
80 dates greater than 1901 to 2038. The local date/time format is derived from a
81 heuristic the first time adodb_getdate is called.
82     
83     
84 ** FUNCTION adodb_date($fmt, $timestamp = false)
85
86 Convert a timestamp to a formatted local date. If $timestamp is not defined, the
87 current timestamp is used. Unlike the function date(), it supports dates
88 outside the 1901 to 2038 range.
89
90 The format fields that adodb_date supports:
91
92 <pre>
93     a - "am" or "pm"
94     A - "AM" or "PM"
95     d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
96     D - day of the week, textual, 3 letters; e.g. "Fri"
97     F - month, textual, long; e.g. "January"
98     g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
99     G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
100     h - hour, 12-hour format; i.e. "01" to "12"
101     H - hour, 24-hour format; i.e. "00" to "23"
102     i - minutes; i.e. "00" to "59"
103     j - day of the month without leading zeros; i.e. "1" to "31"
104     l (lowercase 'L') - day of the week, textual, long; e.g. "Friday" 
105     L - boolean for whether it is a leap year; i.e. "0" or "1"
106     m - month; i.e. "01" to "12"
107     M - month, textual, 3 letters; e.g. "Jan"
108     n - month without leading zeros; i.e. "1" to "12"
109     O - Difference to Greenwich time in hours; e.g. "+0200"
110     Q - Quarter, as in 1, 2, 3, 4
111     r - RFC 2822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200"
112     s - seconds; i.e. "00" to "59"
113     S - English ordinal suffix for the day of the month, 2 characters;
114                    i.e. "st", "nd", "rd" or "th"
115     t - number of days in the given month; i.e. "28" to "31"
116     T - Timezone setting of this machine; e.g. "EST" or "MDT"
117     U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) 
118     w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
119     Y - year, 4 digits; e.g. "1999"
120     y - year, 2 digits; e.g. "99"
121     z - day of the year; i.e. "0" to "365"
122     Z - timezone offset in seconds (i.e. "-43200" to "43200").
123                    The offset for timezones west of UTC is always negative,
124                 and for those east of UTC is always positive.
125 </pre>
126
127 Unsupported:
128 <pre>
129     B - Swatch Internet time
130     I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
131     W - ISO-8601 week number of year, weeks starting on Monday
132
133 </pre>
134
135
136 ** FUNCTION adodb_date2($fmt, $isoDateString = false)
137 Same as adodb_date, but 2nd parameter accepts iso date, eg.
138
139   adodb_date2('d-M-Y H:i','2003-12-25 13:01:34');
140
141  
142 ** FUNCTION adodb_gmdate($fmt, $timestamp = false)
143
144 Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the
145 current timestamp is used. Unlike the function date(), it supports dates
146 outside the 1901 to 2038 range.
147
148
149 ** FUNCTION adodb_mktime($hr, $min, $sec[, $month, $day, $year])
150
151 Converts a local date to a unix timestamp.  Unlike the function mktime(), it supports
152 dates outside the 1901 to 2038 range. All parameters are optional.
153
154
155 ** FUNCTION adodb_gmmktime($hr, $min, $sec [, $month, $day, $year])
156
157 Converts a gmt date to a unix timestamp.  Unlike the function gmmktime(), it supports
158 dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters
159 are currently compulsory.
160
161 ** FUNCTION adodb_gmstrftime($fmt, $timestamp = false)
162 Convert a timestamp to a formatted GMT date.
163
164 ** FUNCTION adodb_strftime($fmt, $timestamp = false)
165
166 Convert a timestamp to a formatted local date. Internally converts $fmt into
167 adodb_date format, then echo result.
168
169 For best results, you can define the local date format yourself. Define a global
170 variable $ADODB_DATE_LOCALE which is an array, 1st element is date format using
171 adodb_date syntax, and 2nd element is the time format, also in adodb_date syntax.
172
173     eg. $ADODB_DATE_LOCALE = array('d/m/Y','H:i:s');
174     
175     Supported format codes:
176
177 <pre>
178     %a - abbreviated weekday name according to the current locale
179     %A - full weekday name according to the current locale
180     %b - abbreviated month name according to the current locale
181     %B - full month name according to the current locale
182     %c - preferred date and time representation for the current locale
183     %d - day of the month as a decimal number (range 01 to 31)
184     %D - same as %m/%d/%y
185     %e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
186     %h - same as %b
187     %H - hour as a decimal number using a 24-hour clock (range 00 to 23)
188     %I - hour as a decimal number using a 12-hour clock (range 01 to 12)
189     %m - month as a decimal number (range 01 to 12)
190     %M - minute as a decimal number
191     %n - newline character
192     %p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
193     %r - time in a.m. and p.m. notation
194     %R - time in 24 hour notation
195     %S - second as a decimal number
196     %t - tab character
197     %T - current time, equal to %H:%M:%S
198     %x - preferred date representation for the current locale without the time
199     %X - preferred time representation for the current locale without the date
200     %y - year as a decimal number without a century (range 00 to 99)
201     %Y - year as a decimal number including the century
202     %Z - time zone or name or abbreviation
203     %% - a literal `%' character
204 </pre>   
205
206     Unsupported codes:
207 <pre>
208     %C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
209     %g - like %G, but without the century.
210     %G - The 4-digit year corresponding to the ISO week number (see %V).
211          This has the same format and value as %Y, except that if the ISO week number belongs
212          to the previous or next year, that year is used instead.
213     %j - day of the year as a decimal number (range 001 to 366)
214     %u - weekday as a decimal number [1,7], with 1 representing Monday
215     %U - week number of the current year as a decimal number, starting
216         with the first Sunday as the first day of the first week
217     %V - The ISO 8601:1988 week number of the current year as a decimal number,
218          range 01 to 53, where week 1 is the first week that has at least 4 days in the
219          current year, and with Monday as the first day of the week. (Use %G or %g for
220          the year component that corresponds to the week number for the specified timestamp.)
221     %w - day of the week as a decimal, Sunday being 0
222     %W - week number of the current year as a decimal number, starting with the
223          first Monday as the first day of the first week
224 </pre>
225
226 =============================================================================
227
228 NOTES
229
230 Useful url for generating test timestamps:
231     http://www.4webhelp.net/us/timestamp.php
232
233 Possible future optimizations include
234
235 a. Using an algorithm similar to Plauger's in "The Standard C Library"
236 (page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not
237 work outside 32-bit signed range, so i decided not to implement it.
238
239 b. Implement daylight savings, which looks awfully complicated, see
240     http://webexhibits.org/daylightsaving/
241
242
243 CHANGELOG
244 - 19 March 2006 0.24
245 Changed strftime() locale detection, because some locales prepend the day of week to the date when %c is used.
246
247 - 10 Feb 2006 0.23
248 PHP5 compat: when we detect PHP5, the RFC2822 format for gmt 0000hrs is changed from -0000 to +0000.
249     In PHP4, we will still use -0000 for 100% compat with PHP4.
250
251 - 08 Sept 2005 0.22
252 In adodb_date2(), $is_gmt not supported properly. Fixed.
253
254 - 18 July  2005 0.21
255 In PHP 4.3.11, the 'r' format has changed. Leading 0 in day is added. Changed for compat.
256 Added support for negative months in adodb_mktime().
257
258 - 24 Feb 2005 0.20
259 Added limited strftime/gmstrftime support. x10 improvement in performance of adodb_date().
260
261 - 21 Dec 2004 0.17
262 In adodb_getdate(), the timestamp was accidentally converted to gmt when $is_gmt is false.
263 Also adodb_mktime(0,0,0) did not work properly. Both fixed thx Mauro.
264
265 - 17 Nov 2004 0.16
266 Removed intval typecast in adodb_mktime() for secs, allowing:
267      adodb_mktime(0,0,0 + 2236672153,1,1,1934);
268 Suggested by Ryan.
269
270 - 18 July 2004 0.15
271 All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory.
272 This brings it more in line with mktime (still not identical).
273
274 - 23 June 2004 0.14
275
276 Allow you to define your own daylights savings function, adodb_daylight_sv.
277 If the function is defined (somewhere in an include), then you can correct for daylights savings.
278
279 In this example, we apply daylights savings in June or July, adding one hour. This is extremely
280 unrealistic as it does not take into account time-zone, geographic location, current year.
281
282 function adodb_daylight_sv(&$arr, $is_gmt)
283 {
284     if ($is_gmt) return;
285     $m = $arr['mon'];
286     if ($m == 6 || $m == 7) $arr['hours'] += 1;
287 }
288
289 This is only called by adodb_date() and not by adodb_mktime().
290
291 The format of $arr is
292 Array (
293    [seconds] => 0
294    [minutes] => 0
295    [hours] => 0
296    [mday] => 1      # day of month, eg 1st day of the month
297    [mon] => 2       # month (eg. Feb)
298    [year] => 2102
299    [yday] => 31     # days in current year
300    [leap] =>        # true if leap year
301    [ndays] => 28    # no of days in current month
302    )
303   
304
305 - 28 Apr 2004 0.13
306 Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov.
307
308 - 20 Mar 2004 0.12
309 Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32.
310
311 - 26 Oct 2003 0.11
312 Because of daylight savings problems (some systems apply daylight savings to
313 January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.
314
315 - 9 Aug 2003 0.10
316 Fixed bug with dates after 2038.
317 See http://phplens.com/lens/lensforum/msgs.php?id=6980
318
319 - 1 July 2003 0.09
320 Added support for Q (Quarter).
321 Added adodb_date2(), which accepts ISO date in 2nd param
322
323 - 3 March 2003 0.08
324 Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS
325 if you want PHP to handle negative timestamps between 1901 to 1969.
326
327 - 27 Feb 2003 0.07
328 All negative numbers handled by adodb now because of RH 7.3+ problems.
329 See http://bugs.php.net/bug.php?id=20048&edit=2
330
331 - 4 Feb 2003 0.06
332 Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates
333 are now correctly handled.
334
335 - 29 Jan 2003 0.05
336
337 Leap year checking differs under Julian calendar (pre 1582). Also
338 leap year code optimized by checking for most common case first.
339
340 We also handle month overflow correctly in mktime (eg month set to 13).
341
342 Day overflow for less than one month's days is supported.
343
344 - 28 Jan 2003 0.04
345
346 Gregorian correction handled. In PHP5, we might throw an error if
347 mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10.
348 Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582.
349
350 - 27 Jan 2003 0.03
351
352 Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION.
353 Fixed calculation of days since start of year for <1970.
354
355 - 27 Jan 2003 0.02
356
357 Changed _adodb_getdate() to inline leap year checking for better performance.
358 Fixed problem with time-zones west of GMT +0000.
359
360 - 24 Jan 2003 0.01
361
362 First implementation.
363 */
364
365
366 /* Initialization */
367
368 /*
369     Version Number
370 */
371 define('ADODB_DATE_VERSION',0.24);
372
373 /*
374     This code was originally for windows. But apparently this problem happens
375     also with Linux, RH 7.3 and later!
376     
377     glibc-2.2.5-34 and greater has been changed to return -1 for dates <
378     1970.  This used to work.  The problem exists with RedHat 7.3 and 8.0
379     echo (mktime(0, 0, 0, 1, 1, 1960));  // prints -1
380     
381     References:
382      http://bugs.php.net/bug.php?id=20048&edit=2
383      http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
384 */
385
386 if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1);
387
388 function adodb_date_test_date($y1,$m,$d=13)
389 {
390     $t = adodb_mktime(0,0,0,$m,$d,$y1);
391     $rez = adodb_date('Y-n-j H:i:s',$t);
392     if ("$y1-$m-$d 00:00:00" != $rez) {
393         print "<b>$y1 error, expected=$y1-$m-$d 00:00:00, adodb=$rez</b><br>";
394         return false;
395     }
396     return true;
397 }
398
399 function adodb_date_test_strftime($fmt)
400 {
401     $s1 = strftime($fmt);
402     $s2 = adodb_strftime($fmt);
403     
404     if ($s1 == $s2) return true;
405     
406     echo "error for $fmt,  strftime=$s1, $adodb=$s2<br>";
407     return false;
408 }
409
410 /**
411      Test Suite
412 */
413 function adodb_date_test()
414 {
415     
416     error_reporting(E_ALL);
417     print "<h4>Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION.' PHP='.PHP_VERSION."</h4>";
418     @set_time_limit(0);
419     $fail = false;
420     
421     // This flag disables calling of PHP native functions, so we can properly test the code
422     if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1);
423     
424     adodb_date_test_strftime('%Y %m %x %X');
425     adodb_date_test_strftime("%A %d %B %Y");
426     adodb_date_test_strftime("%H %M S");
427     
428     $t = adodb_mktime(0,0,0);
429     if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'<br>';
430     
431     $t = adodb_mktime(0,0,0,6,1,2102);
432     if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
433     
434     $t = adodb_mktime(0,0,0,2,1,2102);
435     if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
436     
437     
438     print "<p>Testing gregorian <=> julian conversion<p>";
439     $t = adodb_mktime(0,0,0,10,11,1492);
440     //http://www.holidayorigins.com/html/columbus_day.html - Friday check
441     if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>';
442     
443     $t = adodb_mktime(0,0,0,2,29,1500);
444     if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years<br>';
445     
446     $t = adodb_mktime(0,0,0,2,29,1700);
447     if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years<br>';
448     
449     print  adodb_mktime(0,0,0,10,4,1582).' ';
450     print adodb_mktime(0,0,0,10,15,1582);
451     $diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582));
452     if ($diff != 3600*24) print " <b>Error in gregorian correction = ".($diff/3600/24)." days </b><br>";
453         
454     print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : '<b>Error</b>')."<br>";
455     print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : '<b>Error</b>')."<br>";
456     
457     print "<p>Testing overflow<p>";
458     
459     $t = adodb_mktime(0,0,0,3,33,1965);
460     if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1 <br>';
461     $t = adodb_mktime(0,0,0,4,33,1971);
462     if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2 <br>';
463     $t = adodb_mktime(0,0,0,1,60,1965);
464     if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).' <br>';
465     $t = adodb_mktime(0,0,0,12,32,1965);
466     if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).' <br>';
467     $t = adodb_mktime(0,0,0,12,63,1965);
468     if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).' <br>';
469     $t = adodb_mktime(0,0,0,13,3,1965);
470     if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1 <br>';
471     
472     print "Testing 2-digit => 4-digit year conversion<p>";
473     if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>";
474     if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>";
475     if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>";
476     if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>";
477     if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>";
478     if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>";
479     if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>";
480     
481     // Test string formating
482     print "<p>Testing date formating</p>";
483     $fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C2822 r s t U w y Y z Z 2003';
484     $s1 = date($fmt,0);
485     $s2 = adodb_date($fmt,0);
486     if ($s1 != $s2) {
487         print " date() 0 failed<br>$s1<br>$s2<br>";
488     }
489     flush();
490     for ($i=100; --$i > 0; ) {
491
492         $ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000);
493         $s1 = date($fmt,$ts);
494         $s2 = adodb_date($fmt,$ts);
495         //print "$s1 <br>$s2 <p>";
496         $pos = strcmp($s1,$s2);
497
498         if (($s1) != ($s2)) {
499             for ($j=0,$k=strlen($s1); $j < $k; $j++) {
500                 if ($s1[$j] != $s2[$j]) {
501                     print substr($s1,$j).' ';
502                     break;
503                 }
504             }
505             print "<b>Error date(): $ts<br><pre>
506 &nbsp; \"$s1\" (date len=".strlen($s1).")
507 &nbsp; \"$s2\" (adodb_date len=".strlen($s2).")</b></pre><br>";
508             $fail = true;
509         }
510         
511         $a1 = getdate($ts);
512         $a2 = adodb_getdate($ts);
513         $rez = array_diff($a1,$a2);
514         if (sizeof($rez)>0) {
515             print "<b>Error getdate() $ts</b><br>";
516                 print_r($a1);
517             print "<br>";
518                 print_r($a2);
519             print "<p>";
520             $fail = true;
521         }
522     }
523     
524     // Test generation of dates outside 1901-2038
525     print "<p>Testing random dates between 100 and 4000</p>";
526     adodb_date_test_date(100,1);
527     for ($i=100; --$i >= 0;) {
528         $y1 = 100+rand(0,1970-100);
529         $m = rand(1,12);
530         adodb_date_test_date($y1,$m);
531         
532         $y1 = 3000-rand(0,3000-1970);
533         adodb_date_test_date($y1,$m);
534     }
535     print '<p>';
536     $start = 1960+rand(0,10);
537     $yrs = 12;
538     $i = 365.25*86400*($start-1970);
539     $offset = 36000+rand(10000,60000);
540     $max = 365*$yrs*86400;
541     $lastyear = 0;
542     
543     // we generate a timestamp, convert it to a date, and convert it back to a timestamp
544     // and check if the roundtrip broke the original timestamp value.
545     print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: ";
546     $cnt = 0;
547     for ($max += $i; $i < $max; $i += $offset) {
548         $ret = adodb_date('m,d,Y,H,i,s',$i);
549         $arr = explode(',',$ret);
550         if ($lastyear != $arr[2]) {
551             $lastyear = $arr[2];
552             print " $lastyear ";
553             flush();
554         }
555         $newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]);
556         if ($i != $newi) {
557             print "Error at $i, adodb_mktime returned $newi ($ret)";
558             $fail = true;
559             break;
560         }
561         $cnt += 1;
562     }
563     echo "Tested $cnt dates<br>";
564     if (!$fail) print "<p>Passed !</p>";
565     else print "<p><b>Failed</b> :-(</p>";
566 }
567
568 /**
569     Returns day of week, 0 = Sunday,... 6=Saturday.
570     Algorithm from PEAR::Date_Calc
571 */
572 function adodb_dow($year, $month, $day)
573 {
574 /*
575 Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
576 proclaimed that from that time onwards 3 days would be dropped from the calendar
577 every 400 years.
578
579 Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
580 */
581     if ($year <= 1582) {
582         if ($year < 1582 ||
583             ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
584          else
585             $greg_correction = 0;
586     } else
587         $greg_correction = 0;
588     
589     if($month > 2)
590         $month -= 2;
591     else {
592         $month += 10;
593         $year--;
594     }
595     
596     $day floor((13 * $month - 1) / 5) +
597             $day + ($year % 100) +
598             floor(($year % 100) / 4) +
599             floor(($year / 100) / 4) - 2 *
600             floor($year / 100) + 77 + $greg_correction;
601     
602     return $day - 7 * floor($day / 7);
603 }
604
605
606 /**
607  Checks for leap year, returns true if it is. No 2-digit year check. Also
608  handles julian calendar correctly.
609 */
610 function _adodb_is_leap_year($year)
611 {
612     if ($year % 4 != 0) return false;
613     
614     if ($year % 400 == 0) {