| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
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 245 - 11 Feb 2008 0.33 246 * Bug in 0.32 fix for hour handling. Fixed. 247 248 - 1 Feb 2008 0.32 249 * Now adodb_mktime(0,0,0,12+$m,20,2040) works properly. 250 251 - 10 Jan 2008 0.31 252 * Now adodb_mktime(0,0,0,24,1,2037) works correctly. 253 254 - 15 July 2007 0.30 255 Added PHP 5.2.0 compatability fixes. 256 * gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the 257 * timezone, otherwise we use the current year as the baseline to retrieve the timezone. 258 * Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but 259 in 1970 it was +7:30, then php 5.2 return +7:30, while this library will use +8. 260 * 261 262 - 19 March 2006 0.24 263 Changed strftime() locale detection, because some locales prepend the day of week to the date when %c is used. 264 265 - 10 Feb 2006 0.23 266 PHP5 compat: when we detect PHP5, the RFC2822 format for gmt 0000hrs is changed from -0000 to +0000. 267 In PHP4, we will still use -0000 for 100% compat with PHP4. 268 269 - 08 Sept 2005 0.22 270 In adodb_date2(), $is_gmt not supported properly. Fixed. 271 272 - 18 July 2005 0.21 273 In PHP 4.3.11, the 'r' format has changed. Leading 0 in day is added. Changed for compat. 274 Added support for negative months in adodb_mktime(). 275 276 - 24 Feb 2005 0.20 277 Added limited strftime/gmstrftime support. x10 improvement in performance of adodb_date(). 278 279 - 21 Dec 2004 0.17 280 In adodb_getdate(), the timestamp was accidentally converted to gmt when $is_gmt is false. 281 Also adodb_mktime(0,0,0) did not work properly. Both fixed thx Mauro. 282 283 - 17 Nov 2004 0.16 284 Removed intval typecast in adodb_mktime() for secs, allowing: 285 adodb_mktime(0,0,0 + 2236672153,1,1,1934); 286 Suggested by Ryan. 287 288 - 18 July 2004 0.15 289 All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory. 290 This brings it more in line with mktime (still not identical). 291 292 - 23 June 2004 0.14 293 294 Allow you to define your own daylights savings function, adodb_daylight_sv. 295 If the function is defined (somewhere in an include), then you can correct for daylights savings. 296 297 In this example, we apply daylights savings in June or July, adding one hour. This is extremely 298 unrealistic as it does not take into account time-zone, geographic location, current year. 299 300 function adodb_daylight_sv(&$arr, $is_gmt) 301 { 302 if ($is_gmt) return; 303 $m = $arr['mon']; 304 if ($m == 6 || $m == 7) $arr['hours'] += 1; 305 } 306 307 This is only called by adodb_date() and not by adodb_mktime(). 308 309 The format of $arr is 310 Array ( 311 [seconds] => 0 312 [minutes] => 0 313 [hours] => 0 314 [mday] => 1 # day of month, eg 1st day of the month 315 [mon] => 2 # month (eg. Feb) 316 [year] => 2102 317 [yday] => 31 # days in current year 318 [leap] => # true if leap year 319 [ndays] => 28 # no of days in current month 320 ) 321 322 323 - 28 Apr 2004 0.13 324 Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov. 325 326 - 20 Mar 2004 0.12 327 Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32. 328 329 - 26 Oct 2003 0.11 330 Because of daylight savings problems (some systems apply daylight savings to 331 January!!!), changed adodb_get_gmt_diff() to ignore daylight savings. 332 333 - 9 Aug 2003 0.10 334 Fixed bug with dates after 2038. 335 See http://phplens.com/lens/lensforum/msgs.php?id=6980 336 337 - 1 July 2003 0.09 338 Added support for Q (Quarter). 339 Added adodb_date2(), which accepts ISO date in 2nd param 340 341 - 3 March 2003 0.08 342 Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS 343 if you want PHP to handle negative timestamps between 1901 to 1969. 344 345 - 27 Feb 2003 0.07 346 All negative numbers handled by adodb now because of RH 7.3+ problems. 347 See http://bugs.php.net/bug.php?id=20048&edit=2 348 349 - 4 Feb 2003 0.06 350 Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates 351 are now correctly handled. 352 353 - 29 Jan 2003 0.05 354 355 Leap year checking differs under Julian calendar (pre 1582). Also 356 leap year code optimized by checking for most common case first. 357 358 We also handle month overflow correctly in mktime (eg month set to 13). 359 360 Day overflow for less than one month's days is supported. 361 362 - 28 Jan 2003 0.04 363 364 Gregorian correction handled. In PHP5, we might throw an error if 365 mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10. 366 Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582. 367 368 - 27 Jan 2003 0.03 369 370 Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION. 371 Fixed calculation of days since start of year for <1970. 372 373 - 27 Jan 2003 0.02 374 375 Changed _adodb_getdate() to inline leap year checking for better performance. 376 Fixed problem with time-zones west of GMT +0000. 377 378 - 24 Jan 2003 0.01 379 380 First implementation. 381 */ 382 383 384 /* Initialization */ 385 386 /* 387 Version Number 388 */ 389 define('ADODB_DATE_VERSION',0.33); 390 391 $ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2); 392 393 /* 394 This code was originally for windows. But apparently this problem happens 395 also with Linux, RH 7.3 and later! 396 397 glibc-2.2.5-34 and greater has been changed to return -1 for dates < 398 1970. This used to work. The problem exists with RedHat 7.3 and 8.0 399 echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1 400 401 References: 402 http://bugs.php.net/bug.php?id=20048&edit=2 403 http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html 404 */ 405 406 if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1); 407 408 function adodb_date_test_date($y1,$m,$d=13) 409 { 410 $h = round(rand()% 24); 411 $t = adodb_mktime($h,0,0,$m,$d,$y1); 412 $rez = adodb_date('Y-n-j H:i:s',$t); 413 if ($h == 0) $h = '00'; 414 else if ($h < 10) $h = '0'.$h; 415 if ("$y1-$m-$d $h:00:00" != $rez) { 416 print "<b>$y1 error, expected=$y1-$m-$d $h:00:00, adodb=$rez</b><br>"; 417 return false; 418 } 419 return true; 420 } 421 422 function adodb_date_test_strftime($fmt) 423 { 424 $s1 = strftime($fmt); 425 $s2 = adodb_strftime($fmt); 426 427 if ($s1 == $s2) return true; 428 429 echo "error for $fmt, strftime=$s1, adodb=$s2<br>"; 430 return false; 431 } 432 433 /** 434 Test Suite 435 */ 436 function adodb_date_test() 437 { 438 439 for ($m=-24; $m<=24; $m++) 440 echo "$m :",adodb_date('d-m-Y',adodb_mktime(0,0,0,1+$m,20,2040)),"<br>"; 441 442 error_reporting(E_ALL); 443 print "<h4>Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION.' PHP='.PHP_VERSION."</h4>"; 444 @set_time_limit(0); 445 $fail = false; 446 447 // This flag disables calling of PHP native functions, so we can properly test the code 448 if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1); 449 450 $t = time(); 451 452 453 $fmt = 'Y-m-d H:i:s'; 454 echo '<pre>'; 455 echo 'adodb: ',adodb_date($fmt,$t),'<br>'; 456 echo 'php : ',date($fmt,$t),'<br>'; 457 echo '</pre>'; 458 459 adodb_date_test_strftime('%Y %m %x %X'); 460 adodb_date_test_strftime("%A %d %B %Y"); 461 adodb_date_test_strftime("%H %M S"); 462 463 $t = adodb_mktime(0,0,0); 464 if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'<br>'; 465 466 $t = adodb_mktime(0,0,0,6,1,2102); 467 if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>'; 468 469 $t = adodb_mktime(0,0,0,2,1,2102); 470 if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>'; 471 472 473 print "<p>Testing gregorian <=> julian conversion<p>"; 474 $t = adodb_mktime(0,0,0,10,11,1492); 475 //http://www.holidayorigins.com/html/columbus_day.html - Friday check 476 if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>'; 477 478 $t = adodb_mktime(0,0,0,2,29,1500); 479 if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years<br>'; 480 481 $t = adodb_mktime(0,0,0,2,29,1700); 482 if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years<br>'; 483 484 print adodb_mktime(0,0,0,10,4,1582).' '; 485 print adodb_mktime(0,0,0,10,15,1582); 486 $diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)); 487 if ($diff != 3600*24) print " <b>Error in gregorian correction = ".($diff/3600/24)." days </b><br>"; 488 489 print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : '<b>Error</b>')."<br>"; 490 print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : '<b>Error</b>')."<br>"; 491 492 print "<p>Testing overflow<p>"; 493 494 $t = adodb_mktime(0,0,0,3,33,1965); 495 if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1 <br>'; 496 $t = adodb_mktime(0,0,0,4,33,1971); 497 if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2 <br>'; 498 $t = adodb_mktime(0,0,0,1,60,1965); 499 if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).' <br>'; 500 $t = adodb_mktime(0,0,0,12,32,1965); 501 if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).' <br>'; 502 $t = adodb_mktime(0,0,0,12,63,1965); 503 if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).' <br>'; 504 $t = adodb_mktime(0,0,0,13,3,1965); 505 if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1 <br>'; 506 507 print "Testing 2-digit => 4-digit year conversion<p>"; 508 if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>"; 509 if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>"; 510 if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>"; 511 if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>"; 512 if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>"; 513 if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>"; 514 if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>"; 515 516 // Test string formating 517 print "<p>Testing date formating</p>"; 518 519 $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'; 520 $s1 = date($fmt,0); 521 $s2 = adodb_date($fmt,0); 522 if ($s1 != $s2) { 523 print " date() 0 failed<br>$s1<br>$s2<br>"; 524 } 525 flush(); 526 for ($i=100; --$i > 0; ) { 527 528 $ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000); 529 $s1 = date($fmt,$ts); 530 $s2 = adodb_date($fmt,$ts); 531 //print "$s1 <br>$s2 <p>"; 532 $pos = strcmp($s1,$s2); 533 534 if (($s1) != ($s2)) { 535 for ($j=0,$k=strlen($s1); $j < $k; $j++) { 536 if ($s1[$j] != $s2[$j]) { 537 print substr($s1,$j).' '; 538 break; 539 } 540 } 541 print "<b>Error date(): $ts<br><pre> 542 \"$s1\" (date len=".strlen($s1).") 543 \"$s2\" (adodb_date len=".strlen($s2).")</b></pre><br>"; 544 $fail = true; 545 } 546 547 $a1 = getdate($ts); 548 $a2 = adodb_getdate($ts); 549 $rez = array_diff($a1,$a2); 550 if (sizeof($rez)>0) { 551 print "<b>Error getdate() $ts</b><br>"; 552 print_r($a1); 553 print "<br>"; 554 print_r($a2); 555 print "<p>"; 556 $fail = true; 557 } 558 } 559 560 // Test generation of dates outside 1901-2038 561 print "<p>Testing random dates between 100 and 4000</p>"; 562 adodb_date_test_date(100,1); 563 for ($i=100; --$i >= 0;) { 564 $y1 = 100+rand(0,1970-100); 565 $m = rand(1,12); 566 adodb_date_test_date($y1,$m); 567 568 $y1 = 3000-rand(0,3000-1970); 569 adodb_date_test_date($y1,$m); 570 } 571 print '<p>'; 572 $start = 1960+rand(0,10); 573 $yrs = 12; 574 $i = 365.25*86400*($start-1970); 575 $offset = 36000+rand(10000,60000); 576 $max = 365*$yrs*86400; 577 $lastyear = 0; 578 579 // we generate a timestamp, convert it to a date, and convert it back to a timestamp 580 // and check if the roundtrip broke the original timestamp value. 581 print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: "; 582 $cnt = 0; 583 for ($max += $i; $i < $max; $i += $offset) { 584 $ret = adodb_date('m,d,Y,H,i,s',$i); 585 $arr = explode(',',$ret); 586 if ($lastyear != $arr[2]) { 587 $lastyear = $arr[2]; 588 print " $lastyear "; 589 flush(); 590 } 591 $newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]); 592 if ($i != $newi) { 593 print "Error at $i, adodb_mktime returned $newi ($ret)"; 594 $fail = true; 595 break; 596 } 597 $cnt += 1; 598 } 599 echo "Tested $cnt dates<br>"; 600 if (!$fail) print "<p>Passed !</p>"; 601 else print "<p><b>Failed</b> :-(</p>"; 602 } 603 604 /** 605 Returns day of week, 0 = Sunday,... 6=Saturday. 606 Algorithm from PEAR::Date_Calc 607 */ 608 function adodb_dow($year, $month, $day) 609 { 610 /* 611 Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and 612 proclaimed that from that time onwards 3 days would be dropped from the calendar 613 every 400 years. 614 615 Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). 616 */ 617 if ($year <= 1582) { 618 if ($year < 1582 || 619 ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3; 620 else 621 $greg_correction = 0; 622 } else 623 $greg_correction = 0; 624 625 if($month > 2) 626 $month -= 2; 627 else { 628 $month += 10; 629 $year--; 630 } 631 632 $day = floor((13 * $month - 1) / 5) + 633 $day + ($year % 100) + 634 floor(($year % 100) / 4) + 635 floor(($year / 100) / 4) - 2 * 636 floor($year / 100) + 77 + $greg_correction; 637 638 return $day - 7 * floor($day / 7); 639 } 640 641 642 /** 643 Checks for leap year, returns true if it is. No 2-digit year check. Also 644 handles julian calendar correctly. 645 */ 646 function _adodb_is_leap_year($year) 647 { 648 if ($year % 4 != 0) return false; 649 650 if ($year % 400 == 0) { 651 return true; 652 // if gregorian calendar (>1582), century not-divisible by 400 is not leap 653 } else if ($year > 1582 && $year % 100 == 0 ) { 654 return false; 655 } 656 657 return true; 658 } 659 660 661 /** 662 checks for leap year, returns true if it is. Has 2-digit year check 663 */ 664 function adodb_is_leap_year($year) 665 { 666 return _adodb_is_leap_year(adodb_year_digit_check($year)); 667 } 668 669 /** 670 Fix 2-digit years. Works for any century. 671 Assumes that if 2-digit is more than 30 years in future, then previous century. 672 */ 673 function adodb_year_digit_check($y) 674 { 675 if ($y < 100) { 676 677 $yr = (integer) date("Y"); 678 $century = (integer) ($yr /100); 679 680 if ($yr%100 > 50) { 681 $c1 = $century + 1; 682 $c0 = $century; 683 } else { 684 $c1 = $century; 685 $c0 = $century - 1; 686 } 687 $c1 *= 100; 688 // if 2-digit year is less than 30 years in future, set it to this century 689 // otherwise if more than 30 years in future, then we set 2-digit year to the prev century. 690 if (($y + $c1) < $yr+30) $y = $y + $c1; 691 else $y = $y + $c0*100; 692 } 693 return $y; 694 } 695 696 function adodb_get_gmt_diff_ts($ts) 697 { 698 if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) { 699 $arr = getdate($ts); 700 $y = $arr['year']; 701 $m = $arr['mon']; 702 $d = $arr['mday']; 703 return adodb_get_gmt_diff($y,$m,$d); 704 } else { 705 return adodb_get_gmt_diff(false,false,false); 706 } 707 708 } 709 710 /** 711 get local time zone offset from GMT. Does not handle historical timezones before 1970. 712 */ 713 function adodb_get_gmt_diff($y,$m,$d) 714 { 715 static $TZ,$tzo; 716 global $ADODB_DATETIME_CLASS; 717 718 if (!defined('ADODB_TEST_DATES')) $y = false; 719 else if ($y < 1970 || $y >= 2038) $y = false; 720 721 if ($ADODB_DATETIME_CLASS && $y !== false) { 722 $dt = new DateTime(); 723 $dt->setISODate($y,$m,$d); 724 if (empty($tzo)) { 725 $tzo = new DateTimeZone(date_default_timezone_get()); 726 # $tzt = timezone_transitions_get( $tzo ); 727 } 728 return -$tzo->getOffset($dt); 729 } else { 730 if (isset($TZ)) return $TZ; 731 $y = date('Y'); 732 $TZ = mktime(0,0,0,12,2,$y,0) - gmmktime(0,0,0,12,2,$y,0); 733 } 734 735 return $TZ; 736 } 737 738 /** 739 Returns an array with date info. 740 */ 741 function adodb_getdate($d=false,$fast=false) 742 { 743 if ($d === false) return getdate(); 744 if (!defined('ADODB_TEST_DATES')) { 745 if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range 746 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer 747 return @getdate($d); 748 } 749 } 750 return _adodb_getdate($d); 751 } 752 753 /* 754 // generate $YRS table for _adodb_getdate() 755 function adodb_date_gentable($out=true) 756 { 757 758 for ($i=1970; $i >= 1600; $i-=10) { 759 $s = adodb_gmmktime(0,0,0,1,1,$i); 760 echo "$i => $s,<br>"; 761 } 762 } 763 adodb_date_gentable(); 764 765 for ($i=1970; $i > 1500; $i--) { 766 767 echo "<hr />$i "; 768 adodb_date_test_date($i,1,1); 769 } 770 771 */ 772 773 774 $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); 775 $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); 776 777 function adodb_validdate($y,$m,$d) 778 { 779 global $_month_table_normal,$_month_table_leaf; 780 781 if (_adodb_is_leap_year($y)) $marr = $_month_table_leaf; 782 else $marr = $_month_table_normal; 783 784 if ($m > 12 || $m < 1) return false; 785 786 if ($d > 31 || $d < 1) return false; 787 788 if ($marr[$m] < $d) return false; 789 790 if ($y < 1000 && $y > 3000) return false; 791 792 return true; 793 } 794 795 /** 796 Low-level function that returns the getdate() array. We have a special 797 $fast flag, which if set to true, will return fewer array values, 798 and is much faster as it does not calculate dow, etc. 799 */ 800 function _adodb_getdate($origd=false,$fast=false,$is_gmt=false) 801 { 802 static $YRS; 803 global $_month_table_normal,$_month_table_leaf; 804 805 $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd)); 806 $_day_power = 86400; 807 $_hour_power = 3600; 808 $_min_power = 60; 809 810 if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction 811 812 $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); 813 $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); 814 815 $d366 = $_day_power * 366; 816 $d365 = $_day_power * 365; 817 818 if ($d < 0) { 819 820 if (empty($YRS)) $YRS = array( 821 1970 => 0, 822 1960 => -315619200, 823 1950 => -631152000, 824 1940 => -946771200, 825 1930 => -1262304000, 826 1920 => -1577923200, 827 1910 => -1893456000, 828 1900 => -2208988800, 829 1890 => -2524521600, 830 1880 => -2840140800, 831 1870 => -3155673600, 832 1860 => -3471292800, 833 1850 => -3786825600, 834 1840 => -4102444800, 835 1830 => -4417977600, 836 1820 => -4733596800, 837 1810 => -5049129600, 838 1800 => -5364662400, 839 1790 => -5680195200, 840 1780 => -5995814400, 841 1770 => -6311347200, 842 1760 => -6626966400, 843 1750 => -6942499200, 844 1740 => -7258118400, 845 1730 => -7573651200, 846 1720 => -7889270400, 847 1710 => -8204803200, 848 1700 => -8520336000, 849 1690 => -8835868800, 850 1680 => -9151488000, 851 1670 => -9467020800, 852 1660 => -9782640000, 853 1650 => -10098172800, 854 1640 => -10413792000, 855 1630 => -10729324800, 856 1620 => -11044944000, 857 1610 => -11360476800, 858 1600 => -11676096000); 859 860 if ($is_gmt) $origd = $d; 861 // The valid range of a 32bit signed timestamp is typically from 862 // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT 863 // 864 865 # old algorithm iterates through all years. new algorithm does it in 866 # 10 year blocks 867 868 /* 869 # old algo 870 for ($a = 1970 ; --$a >= 0;) { 871 $lastd = $d; 872 873 if ($leaf = _adodb_is_leap_year($a)) $d += $d366; 874 else $d += $d365; 875 876 if ($d >= 0) { 877 $year = $a; 878 break; 879 } 880 } 881 */ 882 883 $lastsecs = 0; 884 $lastyear = 1970; 885 foreach($YRS as $year => $secs) { 886 if ($d >= $secs) { 887 $a = $lastyear; 888 break; 889 } 890 $lastsecs = $secs; 891 $lastyear = $year; 892 } 893 894 $d -= $lastsecs; 895 if (!isset($a)) $a = $lastyear; 896 897 //echo ' yr=',$a,' ', $d,'.'; 898 899 for (; --$a >= 0;) { 900 $lastd = $d; 901 902 if ($leaf = _adodb_is_leap_year($a)) $d += $d366; 903 else $d += $d365; 904 905 if ($d >= 0) { 906 $year = $a; 907 break; 908 } 909 } 910 /**/ 911 912 $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd; 913 914 $d = $lastd; 915 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; 916 for ($a = 13 ; --$a > 0;) { 917 $lastd = $d; 918 $d += $mtab[$a] * $_day_power; 919 if ($d >= 0) { 920 $month = $a; 921 $ndays = $mtab[$a]; 922 break; 923 } 924 } 925 926 $d = $lastd; 927 $day = $ndays + ceil(($d+1) / ($_day_power)); 928 929 $d += ($ndays - $day+1)* $_day_power; 930 $hour = floor($d/$_hour_power); 931 932 } else { 933 for ($a = 1970 ;; $a++) { 934 $lastd = $d; 935 936 if ($leaf = _adodb_is_leap_year($a)) $d -= $d366; 937 else $d -= $d365; 938 if ($d < 0) { 939 $year = $a; 940 break; 941 } 942 } 943 $secsInYear = $lastd; 944 $d = $lastd; 945 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; 946 for ($a = 1 ; $a <= 12; $a++) { 947 $lastd = $d; 948 $d -= $mtab[$a] * $_day_power; 949 if ($d < 0) { 950 $month = $a; 951 $ndays = $mtab[$a]; 952 break; 953 } 954 } 955 $d = $lastd; 956 $day = ceil(($d+1) / $_day_power); 957 $d = $d - ($day-1) * $_day_power; 958 $hour = floor($d /$_hour_power); 959 } 960 961 $d -= $hour * $_hour_power; 962 $min = floor($d/$_min_power); 963 $secs = $d - $min * $_min_power; 964 if ($fast) { 965 return array( 966 'seconds' => $secs, 967 'minutes' => $min, 968 'hours' => $hour, 969 'mday' => $day, 970 'mon' => $month, 971 'year' => $year, 972 'yday' => floor($secsInYear/$_day_power), 973 'leap' => $leaf, 974 'ndays' => $ndays 975 ); 976 } 977 978 979 $dow = adodb_dow($year,$month,$day); 980 981 return array( 982 'seconds' => $secs, 983 'minutes' => $min, 984 'hours' => $hour, 985 'mday' => $day, 986 'wday' => $dow, 987 'mon' => $month, 988 'year' => $year, 989 'yday' => floor($secsInYear/$_day_power), 990 'weekday' => gmdate('l',$_day_power*(3+$dow)), 991 'month' => gmdate('F',mktime(0,0,0,$month,2,1971)), 992 0 => $origd 993 ); 994 } 995 /* 996 if ($isphp5) 997 $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36); 998 else 999 $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); 1000 break;*/ 1001 function adodb_tz_offset($gmt,$isphp5) 1002 { 1003 $zhrs = abs($gmt)/3600; 1004 $hrs = floor($zhrs); 1005 if ($isphp5) 1006 return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); 1007 else 1008 return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); 1009 break; 1010 } 1011 1012 1013 function adodb_gmdate($fmt,$d=false) 1014 { 1015 return adodb_date($fmt,$d,true); 1016 } 1017 1018 // accepts unix timestamp and iso date format in $d 1019 function adodb_date2($fmt, $d=false, $is_gmt=false) 1020 { 1021 if ($d !== false) { 1022 if (!preg_match( 1023 "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", 1024 ($d), $rr)) return adodb_date($fmt,false,$is_gmt); 1025 1026 if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt); 1027 1028 // h-m-s-MM-DD-YY 1029 if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt); 1030 else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt); 1031 } 1032 1033 return adodb_date($fmt,$d,$is_gmt); 1034 } 1035 1036 1037 /** 1038 Return formatted date based on timestamp $d 1039 */ 1040 function adodb_date($fmt,$d=false,$is_gmt=false) 1041 { 1042 static $daylight; 1043 global $ADODB_DATETIME_CLASS; 1044 1045 if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt); 1046 if (!defined('ADODB_TEST_DATES')) { 1047 if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range 1048 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer 1049 return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); 1050 1051 } 1052 } 1053 $_day_power = 86400; 1054 1055 $arr = _adodb_getdate($d,true,$is_gmt); 1056 1057 if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv'); 1058 if ($daylight) adodb_daylight_sv($arr, $is_gmt); 1059 1060 $year = $arr['year']; 1061 $month = $arr['mon']; 1062 $day = $arr['mday']; 1063 $hour = $arr['hours']; 1064 $min = $arr['minutes']; 1065 $secs = $arr['seconds']; 1066 1067 $max = strlen($fmt); 1068 $dates = ''; 1069 1070 $isphp5 = PHP_VERSION >= 5; 1071 1072 /* 1073 at this point, we have the following integer vars to manipulate: 1074 $year, $month, $day, $hour, $min, $secs 1075 */ 1076 for ($i=0; $i < $max; $i++) { 1077 switch($fmt[$i]) { 1078 case 'T': 1079 if ($ADODB_DATETIME_CLASS) { 1080 $dt = new DateTime(); 1081 $dt->SetDate($year,$month,$day); 1082 $dates .= $dt->Format('T'); 1083 } else 1084 $dates .= date('T'); 1085 break; 1086 // YEAR 1087 case 'L': $dates .= $arr['leap'] ? '1' : '0'; break; 1088 case 'r': // Thu, 21 Dec 2000 16:01:07 +0200 1089 1090 // 4.3.11 uses '04 Jun 2004' 1091 // 4.3.8 uses ' 4 Jun 2004' 1092 $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', ' 1093 . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' '; 1094 1095 if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; 1096 1097 if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min; 1098 1099 if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs; 1100 1101 $gmt = adodb_get_gmt_diff($year,$month,$day); 1102 1103 $dates .= ' '.adodb_tz_offset($gmt,$isphp5); 1104 break; 1105 1106 case 'Y': $dates .= $year; break; 1107 case 'y': $dates .= substr($year,strlen($year)-2,2); break; 1108 // MONTH 1109 case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break; 1110 case 'Q': $dates .= ($month+3)>>2; break; 1111 case 'n': $dates .= $month; break; 1112 case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break; 1113 case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break; 1114 // DAY 1115 case 't': $dates .= $arr['ndays']; break; 1116 case 'z': $dates .= $arr['yday']; break; 1117 case 'w': $dates .= adodb_dow($year,$month,$day); break; 1118 case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break; 1119 case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break; 1120 case 'j': $dates .= $day; break; 1121 case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break; 1122 case 'S': 1123 $d10 = $day % 10; 1124 if ($d10 == 1) $dates .= 'st'; 1125 else if ($d10 == 2 && $day != 12) $dates .= 'nd'; 1126 else if ($d10 == 3) $dates .= 'rd'; 1127 else $dates .= 'th'; 1128 break; 1129 1130 // HOUR 1131 case 'Z': 1132 $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff($year,$month,$day); break; 1133 case 'O': 1134 $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day); 1135 1136 $dates .= adodb_tz_offset($gmt,$isphp5); 1137 break; 1138 1139 case 'H': 1140 if ($hour < 10) $dates .= '0'.$hour; 1141 else $dates .= $hour; 1142 break; 1143 case 'h': 1144 if ($hour > 12) $hh = $hour - 12; 1145 else { 1146 if ($hour == 0) $hh = '12'; 1147 else $hh = $hour; 1148 } 1149 1150 if ($hh < 10) $dates .= '0'.$hh; 1151 else $dates .= $hh; 1152 break; 1153 1154 case 'G': 1155 $dates .= $hour; 1156 break; 1157 1158 case 'g': 1159 if ($hour > 12) $hh = $hour - 12; 1160 else { 1161 if ($hour == 0) $hh = '12'; 1162 else $hh = $hour; 1163 } 1164 $dates .= $hh; 1165 break; 1166 // MINUTES 1167 case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break; 1168 // SECONDS 1169 case 'U': $dates .= $d; break; 1170 case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break; 1171 // AM/PM 1172 // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM 1173 case 'a': 1174 if ($hour>=12) $dates .= 'pm'; 1175 else $dates .= 'am'; 1176 break; 1177 case 'A': 1178 if ($hour>=12) $dates .= 'PM'; 1179 else $dates .= 'AM'; 1180 break; 1181 default: 1182 $dates .= $fmt[$i]; break; 1183 // ESCAPE 1184 case "\\": 1185 $i++; 1186 if ($i < $max) $dates .= $fmt[$i]; 1187 break; 1188 } 1189 } 1190 return $dates; 1191 } 1192 1193 /** 1194 Returns a timestamp given a GMT/UTC time. 1195 Note that $is_dst is not implemented and is ignored. 1196 */ 1197 function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false) 1198 { 1199 return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true); 1200 } 1201 1202 /** 1203 Return a timestamp given a local time. Originally by jackbbs. 1204 Note that $is_dst is not implemented and is ignored. 1205 1206 Not a very fast algorithm - O(n) operation. Could be optimized to O(1). 1207 */ 1208 function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false) 1209 { 1210 if (!defined('ADODB_TEST_DATES')) { 1211 1212 if ($mon === false) { 1213 return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec); 1214 } 1215 1216 // for windows, we don't check 1970 because with timezone differences, 1217 // 1 Jan 1970 could generate negative timestamp, which is illegal 1218 $usephpfns = (1971 < $year && $year < 2038 1219 || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038) 1220 ); 1221 1222 1223 if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false; 1224 1225 if ($usephpfns) { 1226 return $is_gmt ? 1227 @gmmktime($hr,$min,$sec,$mon,$day,$year): 1228 @mktime($hr,$min,$sec,$mon,$day,$year); 1229 } 1230 } 1231 1232 $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$mon,$day); 1233 1234 /* 1235 # disabled because some people place large values in $sec. 1236 # however we need it for $mon because we use an array... 1237 $hr = intval($hr); 1238 $min = intval($min); 1239 $sec = intval($sec); 1240 */ 1241 $mon = intval($mon); 1242 $day = intval($day); 1243 $year = intval($year); 1244 1245 1246 $year = adodb_year_digit_check($year); 1247 1248 if ($mon > 12) { 1249 $y = floor(($mon-1)/ 12); 1250 $year += $y; 1251 $mon -= $y*12; 1252 } else if ($mon < 1) { 1253 $y = ceil((1-$mon) / 12); 1254 $year -= $y; 1255 $mon += $y*12; 1256 } 1257 1258 $_day_power = 86400; 1259 $_hour_power = 3600; 1260 $_min_power = 60; 1261 1262 $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); 1263 $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); 1264 1265 $_total_date = 0; 1266 if ($year >= 1970) { 1267 for ($a = 1970 ; $a <= $year; $a++) { 1268 $leaf = _adodb_is_leap_year($a); 1269 if ($leaf == true) { 1270 $loop_table = $_month_table_leaf; 1271 $_add_date = 366; 1272 } else { 1273 $loop_table = $_month_table_normal; 1274 $_add_date = 365; 1275 } 1276 if ($a < $year) { 1277 $_total_date += $_add_date; 1278 } else { 1279 for($b=1;$b<$mon;$b++) { 1280 $_total_date += $loop_table[$b]; 1281 } 1282 } 1283 } 1284 $_total_date +=$day-1; 1285 $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different; 1286 1287 } else { 1288 for ($a = 1969 ; $a >= $year; $a--) { 1289 $leaf = _adodb_is_leap_year($a); 1290 if ($leaf == true) { 1291 $loop_table = $_month_table_leaf; 1292 $_add_date = 366; 1293 } else { 1294 $loop_table = $_month_table_normal; 1295 $_add_date = 365; 1296 } 1297 if ($a > $year) { $_total_date += $_add_date; 1298 } else { 1299 for($b=12;$b>$mon;$b--) { 1300 $_total_date += $loop_table[$b]; 1301 } 1302 } 1303 } 1304 $_total_date += $loop_table[$mon] - $day; 1305 1306 $_day_time = $hr * $_hour_power + $min * $_min_power + $sec; 1307 $_day_time = $_day_power - $_day_time; 1308 $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different); 1309 if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction 1310 else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582. 1311 } 1312 //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret; 1313 return $ret; 1314 } 1315 1316 function adodb_gmstrftime($fmt, $ts=false) 1317 { 1318 return adodb_strftime($fmt,$ts,true); 1319 } 1320 1321 // hack - convert to adodb_date 1322 function adodb_strftime($fmt, $ts=false,$is_gmt=false) 1323 { 1324 global $ADODB_DATE_LOCALE; 1325 1326 if (!defined('ADODB_TEST_DATES')) { 1327 if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range 1328 if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer 1329 return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts); 1330 1331 } 1332 } 1333 1334 if (empty($ADODB_DATE_LOCALE)) { 1335 /* 1336 $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am 1337 $sep = substr($tstr,2,1); 1338 $hasAM = strrpos($tstr,'M') !== false; 1339 */ 1340 # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24 1341 $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am 1342 $sep = substr($dstr,2,1); 1343 $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am 1344 $hasAM = strrpos($tstr,'M') !== false; 1345 1346 $ADODB_DATE_LOCALE = array(); 1347 $ADODB_DATE_LOCALE[] = strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y'; 1348 $ADODB_DATE_LOCALE[] = ($hasAM) ? 'h:i:s a' : 'H:i:s'; 1349 1350 } 1351 $inpct = false; 1352 $fmtdate = ''; 1353 for ($i=0,$max = strlen($fmt); $i < $max; $i++) { 1354 $ch = $fmt[$i]; 1355 if ($ch == '%') { 1356 if ($inpct) { 1357 $fmtdate .= '%'; 1358 $inpct = false; 1359 } else 1360 $inpct = true; 1361 } else if ($inpct) { 1362 1363 $inpct = false; 1364 switch($ch) { 1365 case '0': 1366 case '1': 1367 case '2': 1368 case '3': 1369 case '4': 1370 case '5': 1371 case '6': 1372 case '7': 1373 case '8': 1374 case '9': 1375 case 'E': 1376 case 'O': 1377 /* ignore format modifiers */ 1378 $inpct = true; 1379 break; 1380 1381 case 'a': $fmtdate .= 'D'; break; 1382 case 'A': $fmtdate .= 'l'; break; 1383 case 'h': 1384 case 'b': $fmtdate .= 'M'; break; 1385 case 'B': $fmtdate .= 'F'; break; 1386 case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break; 1387 case 'C': $fmtdate .= '\C?'; break; // century 1388 case 'd': $fmtdate .= 'd'; break; 1389 case 'D': $fmtdate .= 'm/d/y'; break; 1390 case 'e': $fmtdate .= 'j'; break; 1391 case 'g': $fmtdate .= '\g?'; break; //? 1392 case 'G': $fmtdate .= '\G?'; break; //? 1393 case 'H': $fmtdate .= 'H'; break; 1394 case 'I': $fmtdate .= 'h'; break; 1395 case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd 1396 case 'm': $fmtdate .= 'm'; break; 1397 case 'M': $fmtdate .= 'i'; break; 1398 case 'n': $fmtdate .= "\n"; break; 1399 case 'p': $fmtdate .= 'a'; break; 1400 case 'r': $fmtdate .= 'h:i:s a'; break; 1401 case 'R': $fmtdate .= 'H:i:s'; break; 1402 case 'S': $fmtdate .= 's'; break; 1403 case 't': $fmtdate .= "\t"; break; 1404 case 'T': $fmtdate .= 'H:i:s'; break; 1405 case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based 1406 case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based 1407 case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break; 1408 case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break; 1409 case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based 1410 case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based 1411 case 'y': $fmtdate .= 'y'; break; 1412 case 'Y': $fmtdate .= 'Y'; break; 1413 case 'Z': $fmtdate .= 'T'; break; 1414 } 1415 } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' )) 1416 $fmtdate .= "\\".$ch; 1417 else 1418 $fmtdate .= $ch; 1419 } 1420 //echo "fmt=",$fmtdate,"<br>"; 1421 if ($ts === false) $ts = time(); 1422 $ret = adodb_date($fmtdate, $ts, $is_gmt); 1423 return $ret; 1424 } 1425 1426 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |