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