[ Index ] |
|
Code source de PRADO 3.0.6 |
1 <?php 2 /** 3 * TDateTimeStamp class file. 4 * 5 * COPYRIGHT 6 * (c) 2003-2005 John Lim and released under BSD-style license except for code by 7 * jackbbs, which includes getTimeStamp, getGMTDiff, isLeapYear 8 * and originally found at http://www.php.net/manual/en/function.mktime.php 9 * 10 * @author Wei Zhuo <weizhuo[at]gamil[dot]com> 11 * @link http://www.pradosoft.com/ 12 * @copyright Copyright © 2006 PradoSoft 13 * @license http://www.pradosoft.com/license/ 14 * @version $Revision: 30/08/2006 $ 15 * @package System.Util 16 */ 17 18 /* 19 This code was originally for windows. But apparently this problem happens 20 also with Linux, RH 7.3 and later! 21 22 glibc-2.2.5-34 and greater has been changed to return -1 for dates < 23 1970. This used to work. The problem exists with RedHat 7.3 and 8.0 24 echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1 25 26 References: 27 http://bugs.php.net/bug.php?id=20048&edit=2 28 http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html 29 */ 30 31 if (!defined('ADODB_ALLOW_NEGATIVE_TS') 32 && !defined('ADODB_NO_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1); 33 34 /** 35 * TDateTimeStamp Class 36 * 37 * TDateTimeStamp Class is adpated from the ADOdb Date Library, 38 * part of the ADOdb abstraction library 39 * Download: http://phplens.com/phpeverywhere/ 40 * 41 * http://phplens.com/phpeverywhere/adodb_date_library 42 * 43 * PHP native date functions use integer timestamps for computations. 44 * Because of this, dates are restricted to the years 1901-2038 on Unix 45 * and 1970-2038 on Windows due to integer overflow for dates beyond 46 * those years. This library overcomes these limitations by replacing the 47 * native function's signed integers (normally 32-bits) with PHP floating 48 * point numbers (normally 64-bits). 49 * 50 * Dates from 100 A.D. to 3000 A.D. and later have been tested. The minimum 51 * is 100 A.D. as <100 will invoke the 2 => 4 digit year conversion. 52 * The maximum is billions of years in the future, but this is a theoretical 53 * limit as the computation of that year would take too long with the 54 * current implementation of {@link getTimeStamp}. 55 * 56 * PERFORMANCE 57 * For high speed, this library uses the native date functions where 58 * possible, and only switches to PHP code when the dates fall outside 59 * the 32-bit signed integer range. 60 * 61 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> 62 * @version $Revision: $ 30/08/2006 $ 63 * @package System.Util 64 * @since 3.0.4 65 */ 66 class TDateTimeStamp 67 { 68 protected static $_month_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); 69 protected static $_month_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31); 70 71 /** 72 * Gets day of week, 0 = Sunday,... 6=Saturday. 73 * Algorithm from PEAR::Date_Calc 74 */ 75 public function getDayofWeek($year, $month, $day) 76 { 77 /* 78 Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and 79 proclaimed that from that time onwards 3 days would be dropped from the calendar 80 every 400 years. 81 82 Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). 83 */ 84 if ($year <= 1582) 85 { 86 if ($year < 1582 || 87 ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) 88 { 89 $greg_correction = 3; 90 } 91 else 92 { 93 $greg_correction = 0; 94 } 95 } 96 else 97 { 98 $greg_correction = 0; 99 } 100 101 if($month > 2) 102 $month -= 2; 103 else 104 { 105 $month += 10; 106 $year--; 107 } 108 109 $day = floor((13 * $month - 1) / 5) + 110 $day + ($year % 100) + 111 floor(($year % 100) / 4) + 112 floor(($year / 100) / 4) - 2 * 113 floor($year / 100) + 77 + $greg_correction; 114 115 return $day - 7 * floor($day / 7); 116 } 117 118 /** 119 * Checks for leap year, returns true if it is. No 2-digit year check. Also 120 * handles julian calendar correctly. 121 * @param float year to check 122 * @return boolean true if is leap year 123 */ 124 public function isLeapYear($year) 125 { 126 $year = $this->digitCheck($year); 127 if ($year % 4 != 0) 128 return false; 129 130 if ($year % 400 == 0) 131 return true; 132 // if gregorian calendar (>1582), century not-divisible by 400 is not leap 133 else if ($year > 1582 && $year % 100 == 0 ) 134 return false; 135 return true; 136 } 137 138 /** 139 * Fix 2-digit years. Works for any century. 140 * Assumes that if 2-digit is more than 30 years in future, then previous century. 141 * @return integer change two digit year into multiple digits 142 */ 143 protected function digitCheck($y) 144 { 145 if ($y < 100){ 146 $yr = (integer) date("Y"); 147 $century = (integer) ($yr /100); 148 149 if ($yr%100 > 50) { 150 $c1 = $century + 1; 151 $c0 = $century; 152 } else { 153 $c1 = $century; 154 $c0 = $century - 1; 155 } 156 $c1 *= 100; 157 // if 2-digit year is less than 30 years in future, set it to this century 158 // otherwise if more than 30 years in future, then we set 2-digit year to the prev century. 159 if (($y + $c1) < $yr+30) $y = $y + $c1; 160 else $y = $y + $c0*100; 161 } 162 return $y; 163 } 164 165 public function get4DigitYear($y) 166 { 167 return $this->digitCheck($y); 168 } 169 170 /** 171 * @return integer get local time zone offset from GMT 172 */ 173 public function getGMTDiff() 174 { 175 static $TZ; 176 if (isset($TZ)) return $TZ; 177 178 $TZ = mktime(0,0,0,1,2,1970) - gmmktime(0,0,0,1,2,1970); 179 return $TZ; 180 } 181 182 /** 183 * @return array an array with date info. 184 */ 185 function getDate($d=false,$fast=false) 186 { 187 if ($d === false) return getdate(); 188 // check if number in 32-bit signed range 189 if ((abs($d) <= 0x7FFFFFFF)) 190 { 191 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer 192 return @getdate($d); 193 } 194 return $this->_getDateInternal($d); 195 } 196 197 198 199 /** 200 * Low-level function that returns the getdate() array. We have a special 201 * $fast flag, which if set to true, will return fewer array values, 202 * and is much faster as it does not calculate dow, etc. 203 * @param float orginal date 204 * @param boolean false to compute the day of the week, default is true 205 * @param boolean true to calculate the GMT dates 206 * @return array an array with date info. 207 */ 208 protected function _getDateInternal($origd=false,$fast=true,$is_gmt=false) 209 { 210 static $YRS; 211 212 $d = $origd - ($is_gmt ? 0 : $this->getGMTDiff()); 213 214 $_day_power = 86400; 215 $_hour_power = 3600; 216 $_min_power = 60; 217 218 if ($d < -12219321600) 219 $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction 220 221 $_month_table_normal =& self::$_month_normal; 222 $_month_table_leaf = & self::$_month_leaf; 223 224 $d366 = $_day_power * 366; 225 $d365 = $_day_power * 365; 226 227 if ($d < 0) 228 { 229 if (empty($YRS)) 230 $YRS = array( 231 1970 => 0, 232 1960 => -315619200, 233 1950 => -631152000, 234 1940 => -946771200, 235 1930 => -1262304000, 236 1920 => -1577923200, 237 1910 => -1893456000, 238 1900 => -2208988800, 239 1890 => -2524521600, 240 1880 => -2840140800, 241 1870 => -3155673600, 242 1860 => -3471292800, 243 1850 => -3786825600, 244 1840 => -4102444800, 245 1830 => -4417977600, 246 1820 => -4733596800, 247 1810 => -5049129600, 248 1800 => -5364662400, 249 1790 => -5680195200, 250 1780 => -5995814400, 251 1770 => -6311347200, 252 1760 => -6626966400, 253 1750 => -6942499200, 254 1740 => -7258118400, 255 1730 => -7573651200, 256 1720 => -7889270400, 257 1710 => -8204803200, 258 1700 => -8520336000, 259 1690 => -8835868800, 260 1680 => -9151488000, 261 1670 => -9467020800, 262 1660 => -9782640000, 263 1650 => -10098172800, 264 1640 => -10413792000, 265 1630 => -10729324800, 266 1620 => -11044944000, 267 1610 => -11360476800, 268 1600 => -11676096000); 269 270 if ($is_gmt) 271 $origd = $d; 272 // The valid range of a 32bit signed timestamp is typically from 273 // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT 274 // 275 276 # old algorithm iterates through all years. new algorithm does it in 277 # 10 year blocks 278 279 /* 280 # old algo 281 for ($a = 1970 ; --$a >= 0;) { 282 $lastd = $d; 283 284 if ($leaf = _adodb_is_leap_year($a)) $d += $d366; 285 else $d += $d365; 286 287 if ($d >= 0) { 288 $year = $a; 289 break; 290 } 291 } 292 */ 293 294 $lastsecs = 0; 295 $lastyear = 1970; 296 foreach($YRS as $year => $secs) 297 { 298 if ($d >= $secs) 299 { 300 $a = $lastyear; 301 break; 302 } 303 $lastsecs = $secs; 304 $lastyear = $year; 305 } 306 307 $d -= $lastsecs; 308 if (!isset($a)) $a = $lastyear; 309 310 //echo ' yr=',$a,' ', $d,'.'; 311 312 for (; --$a >= 0;) 313 { 314 $lastd = $d; 315 316 if ($leaf = $this->isLeapYear($a)) 317 $d += $d366; 318 else 319 $d += $d365; 320 321 if ($d >= 0) 322 { 323 $year = $a; 324 break; 325 } 326 } 327 /**/ 328 329 $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd; 330 331 $d = $lastd; 332 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; 333 for ($a = 13 ; --$a > 0;) 334 { 335 $lastd = $d; 336 $d += $mtab[$a] * $_day_power; 337 if ($d >= 0) 338 { 339 $month = $a; 340 $ndays = $mtab[$a]; 341 break; 342 } 343 } 344 345 $d = $lastd; 346 $day = $ndays + ceil(($d+1) / ($_day_power)); 347 348 $d += ($ndays - $day+1)* $_day_power; 349 $hour = floor($d/$_hour_power); 350 351 } else { 352 for ($a = 1970 ;; $a++) 353 { 354 $lastd = $d; 355 356 if ($leaf = $this->isLeapYear($a)) $d -= $d366; 357 else $d -= $d365; 358 if ($d < 0) 359 { 360 $year = $a; 361 break; 362 } 363 } 364 $secsInYear = $lastd; 365 $d = $lastd; 366 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal; 367 for ($a = 1 ; $a <= 12; $a++) 368 { 369 $lastd = $d; 370 $d -= $mtab[$a] * $_day_power; 371 if ($d < 0) 372 { 373 $month = $a; 374 $ndays = $mtab[$a]; 375 break; 376 } 377 } 378 $d = $lastd; 379 $day = ceil(($d+1) / $_day_power); 380 $d = $d - ($day-1) * $_day_power; 381 $hour = floor($d /$_hour_power); 382 } 383 384 $d -= $hour * $_hour_power; 385 $min = floor($d/$_min_power); 386 $secs = $d - $min * $_min_power; 387 if ($fast) 388 { 389 return array( 390 'seconds' => $secs, 391 'minutes' => $min, 392 'hours' => $hour, 393 'mday' => $day, 394 'mon' => $month, 395 'year' => $year, 396 'yday' => floor($secsInYear/$_day_power), 397 'leap' => $leaf, 398 'ndays' => $ndays 399 ); 400 } 401 402 403 $dow = $this->getDayofWeek($year,$month,$day); 404 405 return array( 406 'seconds' => $secs, 407 'minutes' => $min, 408 'hours' => $hour, 409 'mday' => $day, 410 'wday' => $dow, 411 'mon' => $month, 412 'year' => $year, 413 'yday' => floor($secsInYear/$_day_power), 414 'weekday' => gmdate('l',$_day_power*(3+$dow)), 415 'month' => gmdate('F',mktime(0,0,0,$month,2,1971)), 416 0 => $origd 417 ); 418 } 419 420 /** 421 * @return boolean true if valid date, semantic check only. 422 */ 423 public function isValidDate($y,$m,$d) 424 { 425 if ($this->isLeapYear($y)) 426 $marr =& self::$_month_leaf; 427 else 428 $marr =& self::$_month_normal; 429 430 if ($m > 12 || $m < 1) return false; 431 432 if ($d > 31 || $d < 1) return false; 433 434 if ($marr[$m] < $d) return false; 435 436 if ($y < 1000 && $y > 3000) return false; 437 438 return true; 439 } 440 441 /** 442 * @return string formatted date based on timestamp $d 443 */ 444 function formatDate($fmt,$d=false,$is_gmt=false) 445 { 446 if ($d === false) 447 return ($is_gmt)? @gmdate($fmt): @date($fmt); 448 449 // check if number in 32-bit signed range 450 if ((abs($d) <= 0x7FFFFFFF)) 451 { 452 // if windows, must be +ve integer 453 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) 454 return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); 455 } 456 457 $_day_power = 86400; 458 459 $arr = $this->getDate($d,true,$is_gmt); 460 461 $year = $arr['year']; 462 $month = $arr['mon']; 463 $day = $arr['mday']; 464 $hour = $arr['hours']; 465 $min = $arr['minutes']; 466 $secs = $arr['seconds']; 467 468 $max = strlen($fmt); 469 $dates = ''; 470 471 $isphp5 = PHP_VERSION >= 5; 472 473 /* 474 at this point, we have the following integer vars to manipulate: 475 $year, $month, $day, $hour, $min, $secs 476 */ 477 for ($i=0; $i < $max; $i++) 478 { 479 switch($fmt[$i]) 480 { 481 case 'T': $dates .= date('T');break; 482 // YEAR 483 case 'L': $dates .= $arr['leap'] ? '1' : '0'; break; 484 case 'r': // Thu, 21 Dec 2000 16:01:07 +0200 485 486 // 4.3.11 uses '04 Jun 2004' 487 // 4.3.8 uses ' 4 Jun 2004' 488 $dates .= gmdate('D',$_day_power*(3+$this->getDayOfWeek($year,$month,$day))).', ' 489 . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' '; 490 491 if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; 492 493 if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min; 494 495 if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs; 496 497 $gmt = $this->getGMTDiff(); 498 if ($isphp5) 499 $dates .= sprintf(' %s%04d',($gmt<=0)?'+':'-',abs($gmt)/36); 500 else 501 $dates .= sprintf(' %s%04d',($gmt<0)?'+':'-',abs($gmt)/36); 502 break; 503 504 case 'Y': $dates .= $year; break; 505 case 'y': $dates .= substr($year,strlen($year)-2,2); break; 506 // MONTH 507 case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break; 508 case 'Q': $dates .= ($month+3)>>2; break; 509 case 'n': $dates .= $month; break; 510 case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break; 511 case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break; 512 // DAY 513 case 't': $dates .= $arr['ndays']; break; 514 case 'z': $dates .= $arr['yday']; break; 515 case 'w': $dates .= $this->getDayOfWeek($year,$month,$day); break; 516 case 'l': $dates .= gmdate('l',$_day_power*(3+$this->getDayOfWeek($year,$month,$day))); break; 517 case 'D': $dates .= gmdate('D',$_day_power*(3+$this->getDayOfWeek($year,$month,$day))); break; 518 case 'j': $dates .= $day; break; 519 case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break; 520 case 'S': 521 $d10 = $day % 10; 522 if ($d10 == 1) $dates .= 'st'; 523 else if ($d10 == 2 && $day != 12) $dates .= 'nd'; 524 else if ($d10 == 3) $dates .= 'rd'; 525 else $dates .= 'th'; 526 break; 527 528 // HOUR 529 case 'Z': 530 $dates .= ($is_gmt) ? 0 : -$this->getGMTDiff(); break; 531 case 'O': 532 $gmt = ($is_gmt) ? 0 : $this->getGMTDiff(); 533 534 if ($isphp5) 535 $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36); 536 else 537 $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); 538 break; 539 540 case 'H': 541 if ($hour < 10) $dates .= '0'.$hour; 542 else $dates .= $hour; 543 break; 544 case 'h': 545 if ($hour > 12) $hh = $hour - 12; 546 else { 547 if ($hour == 0) $hh = '12'; 548 else $hh = $hour; 549 } 550 551 if ($hh < 10) $dates .= '0'.$hh; 552 else $dates .= $hh; 553 break; 554 555 case 'G': 556 $dates .= $hour; 557 break; 558 559 case 'g': 560 if ($hour > 12) $hh = $hour - 12; 561 else { 562 if ($hour == 0) $hh = '12'; 563 else $hh = $hour; 564 } 565 $dates .= $hh; 566 break; 567 // MINUTES 568 case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break; 569 // SECONDS 570 case 'U': $dates .= $d; break; 571 case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break; 572 // AM/PM 573 // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM 574 case 'a': 575 if ($hour>=12) $dates .= 'pm'; 576 else $dates .= 'am'; 577 break; 578 case 'A': 579 if ($hour>=12) $dates .= 'PM'; 580 else $dates .= 'AM'; 581 break; 582 default: 583 $dates .= $fmt[$i]; break; 584 // ESCAPE 585 case "\\": 586 $i++; 587 if ($i < $max) $dates .= $fmt[$i]; 588 break; 589 } 590 } 591 return $dates; 592 } 593 594 /** 595 * Not a very fast algorithm - O(n) operation. Could be optimized to O(1). 596 * @return integer|float a timestamp given a local time. Originally by jackbbs. 597 */ 598 function getTimeStamp($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_gmt=false) 599 { 600 601 if ($mon === false) 602 return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec); 603 604 // for windows, we don't check 1970 because with timezone differences, 605 // 1 Jan 1970 could generate negative timestamp, which is illegal 606 if (1971 <= $year && $year < 2038 || !defined('ADODB_NO_NEGATIVE_TS') 607 && (1901 < $year && $year < 2038)) 608 { 609 return $is_gmt ? @gmmktime($hr,$min,$sec,$mon,$day,$year) 610 : @mktime($hr,$min,$sec,$mon,$day,$year); 611 } 612 613 $gmt_different = ($is_gmt) ? 0 : $this->getGMTDiff(); 614 615 /* 616 # disabled because some people place large values in $sec. 617 # however we need it for $mon because we use an array... 618 $hr = intval($hr); 619 $min = intval($min); 620 $sec = intval($sec); 621 */ 622 $mon = intval($mon); 623 $day = intval($day); 624 $year = intval($year); 625 626 627 $year = $this->digitCheck($year); 628 629 if ($mon > 12) 630 { 631 $y = floor($mon / 12); 632 $year += $y; 633 $mon -= $y*12; 634 } 635 else if ($mon < 1) 636 { 637 $y = ceil((1-$mon) / 12); 638 $year -= $y; 639 $mon += $y*12; 640 } 641 642 $_day_power = 86400; 643 $_hour_power = 3600; 644 $_min_power = 60; 645 646 $_month_table_normal = & self::$_month_normal; 647 $_month_table_leaf = & self::$_month_leaf; 648 649 $_total_date = 0; 650 if ($year >= 1970) 651 { 652 for ($a = 1970 ; $a <= $year; $a++) 653 { 654 $leaf = $this->isLeapYear($a); 655 if ($leaf == true) { 656 $loop_table = $_month_table_leaf; 657 $_add_date = 366; 658 } else { 659 $loop_table = $_month_table_normal; 660 $_add_date = 365; 661 } 662 if ($a < $year) { 663 $_total_date += $_add_date; 664 } else { 665 for($b=1;$b<$mon;$b++) { 666 $_total_date += $loop_table[$b]; 667 } 668 } 669 } 670 $_total_date +=$day-1; 671 $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different; 672 673 } else { 674 for ($a = 1969 ; $a >= $year; $a--) { 675 $leaf = $this->isLeapYear($a); 676 if ($leaf == true) { 677 $loop_table = $_month_table_leaf; 678 $_add_date = 366; 679 } else { 680 $loop_table = $_month_table_normal; 681 $_add_date = 365; 682 } 683 if ($a > $year) { $_total_date += $_add_date; 684 } else { 685 for($b=12;$b>$mon;$b--) { 686 $_total_date += $loop_table[$b]; 687 } 688 } 689 } 690 $_total_date += $loop_table[$mon] - $day; 691 692 $_day_time = $hr * $_hour_power + $min * $_min_power + $sec; 693 $_day_time = $_day_power - $_day_time; 694 $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different); 695 if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction 696 else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582. 697 } 698 //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret; 699 return $ret; 700 } 701 } 702 703 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |