[ Index ]

PHP Cross Reference of MyBB

title

Body

[close]

/inc/ -> functions_time.php (source)

   1  <?php
   2  /** This file is distributed with MyBB under the BSD License package and modified to work with MyBB **/
   3  
   4  /**
   5  ADOdb Date Library, part of the ADOdb abstraction library
   6  Download: http://phplens.com/phpeverywhere/
   7  
   8  PHP native date functions use integer timestamps for computations.
   9  Because of this, dates are restricted to the years 1901-2038 on Unix 
  10  and 1970-2038 on Windows due to integer overflow for dates beyond 
  11  those years. This library overcomes these limitations by replacing the 
  12  native function's signed integers (normally 32-bits) with PHP floating 
  13  point numbers (normally 64-bits).
  14  
  15  Dates from 100 A.D. to 3000 A.D. and later
  16  have been tested. The minimum is 100 A.D. as <100 will invoke the
  17  2 => 4 digit year conversion. The maximum is billions of years in the 
  18  future, but this is a theoretical limit as the computation of that year 
  19  would take too long with the current implementation of adodb_mktime().
  20  
  21  This library replaces native functions as follows:
  22  
  23  <pre>    
  24      getdate()  with  adodb_getdate()
  25      date()     with  adodb_date() 
  26      gmdate()   with  adodb_gmdate()
  27      mktime()   with  adodb_mktime()
  28      gmmktime() with  adodb_gmmktime()
  29      strftime() with  adodb_strftime()
  30      strftime() with  adodb_gmstrftime()
  31  </pre>
  32      
  33  The parameters are identical, except that adodb_date() accepts a subset
  34  of date()'s field formats. Mktime() will convert from local time to GMT, 
  35  and date() will convert from GMT to local time, but daylight savings is 
  36  not handled currently.
  37  
  38  This library is independant of the rest of ADOdb, and can be used
  39  as standalone code.
  40  
  41  PERFORMANCE
  42  
  43  For high speed, this library uses the native date functions where
  44  possible, and only switches to PHP code when the dates fall outside 
  45  the 32-bit signed integer range.
  46  
  47  GREGORIAN CORRECTION
  48  
  49  Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, 
  50  October 4, 1582 (Julian) was followed immediately by Friday, October 15, 
  51  1582 (Gregorian). 
  52  
  53  Since 0.06, we handle this correctly, so:
  54  
  55  adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) 
  56      == 24 * 3600 (1 day)
  57  
  58  =============================================================================
  59  
  60  COPYRIGHT
  61  
  62  (c) 2003-2005 John Lim and released under BSD-style license except for code by 
  63  jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
  64  and originally found at http://www.php.net/manual/en/function.mktime.php
  65  
  66  =============================================================================
  67  
  68  BUG REPORTS
  69  
  70  These should be posted to the ADOdb forums at
  71  
  72      http://phplens.com/lens/lensforum/topics.php?id=4
  73  
  74  =============================================================================
  75  */
  76  
  77  
  78  /* Initialization */
  79  
  80  /*
  81      Version Number
  82  */
  83  define('ADODB_DATE_VERSION', 0.33);
  84  
  85  $ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2);
  86  
  87  /*
  88      This code was originally for windows. But apparently this problem happens 
  89      also with Linux, RH 7.3 and later!
  90      
  91      glibc-2.2.5-34 and greater has been changed to return -1 for dates <
  92      1970.  This used to work.  The problem exists with RedHat 7.3 and 8.0
  93      echo (mktime(0, 0, 0, 1, 1, 1960));  // prints -1
  94      
  95      References:
  96       http://bugs.php.net/bug.php?id=20048&edit=2
  97       http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
  98  */
  99  
 100  if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1);
 101  
 102  /**
 103      Returns day of week, 0 = Sunday,... 6=Saturday. 
 104      Algorithm from PEAR::Date_Calc
 105  */
 106  function adodb_dow($year, $month, $day)
 107  {
 108  /*
 109  Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and 
 110  proclaimed that from that time onwards 3 days would be dropped from the calendar 
 111  every 400 years.
 112  
 113  Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian). 
 114  */
 115      if ($year <= 1582) {
 116          if ($year < 1582 || 
 117              ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
 118           else
 119              $greg_correction = 0;
 120      } else
 121          $greg_correction = 0;
 122      
 123      if($month > 2)
 124          $month -= 2;
 125      else {
 126          $month += 10;
 127          $year--;
 128      }
 129      
 130      $day =  floor((13 * $month - 1) / 5) +
 131              $day + ($year % 100) +
 132              floor(($year % 100) / 4) +
 133              floor(($year / 100) / 4) - 2 *
 134              floor($year / 100) + 77 + $greg_correction;
 135      
 136      return $day - 7 * floor($day / 7);
 137  }
 138  
 139  
 140  /**
 141   Checks for leap year, returns true if it is. No 2-digit year check. Also 
 142   handles julian calendar correctly.
 143  */
 144  function _adodb_is_leap_year($year) 
 145  {
 146      if ($year % 4 != 0) return false;
 147      
 148      if ($year % 400 == 0) {
 149          return true;
 150      // if gregorian calendar (>1582), century not-divisible by 400 is not leap
 151      } else if ($year > 1582 && $year % 100 == 0 ) {
 152          return false;
 153      } 
 154      
 155      return true;
 156  }
 157  
 158  
 159  /**
 160   checks for leap year, returns true if it is. Has 2-digit year check
 161  */
 162  function adodb_is_leap_year($year) 
 163  {
 164      return  _adodb_is_leap_year(adodb_year_digit_check($year));
 165  }
 166  
 167  /**
 168      Fix 2-digit years. Works for any century.
 169       Assumes that if 2-digit is more than 30 years in future, then previous century.
 170  */
 171  function adodb_year_digit_check($y) 
 172  {
 173      if ($y < 100) {
 174      
 175          $yr = (integer) date("Y");
 176          $century = (integer) ($yr /100);
 177          
 178          if ($yr%100 > 50) {
 179              $c1 = $century + 1;
 180              $c0 = $century;
 181          } else {
 182              $c1 = $century;
 183              $c0 = $century - 1;
 184          }
 185          $c1 *= 100;
 186          // if 2-digit year is less than 30 years in future, set it to this century
 187          // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
 188          if (($y + $c1) < $yr+30) $y = $y + $c1;
 189          else $y = $y + $c0*100;
 190      }
 191      return $y;
 192  }
 193  
 194  function adodb_get_gmt_diff_ts($ts) 
 195  {
 196      if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) {
 197          $arr = getdate($ts);
 198          $y = $arr['year'];
 199          $m = $arr['mon'];
 200          $d = $arr['mday'];
 201          return adodb_get_gmt_diff($y,$m,$d);    
 202      } else {
 203          return adodb_get_gmt_diff(false,false,false);
 204      }
 205      
 206  }
 207  
 208  /**
 209   get local time zone offset from GMT. Does not handle historical timezones before 1970.
 210  */
 211  function adodb_get_gmt_diff($y,$m,$d) 
 212  {
 213  static $TZ,$tzo;
 214  global $ADODB_DATETIME_CLASS;
 215  
 216      if (!defined('ADODB_TEST_DATES')) $y = false;
 217      else if ($y < 1970 || $y >= 2038) $y = false;
 218  
 219      if ($ADODB_DATETIME_CLASS && $y !== false) {
 220          $dt = new DateTime();
 221          $dt->setISODate($y,$m,$d);
 222          if (empty($tzo)) {
 223              $tzo = new DateTimeZone(date_default_timezone_get());
 224          #    $tzt = timezone_transitions_get( $tzo );
 225          }
 226          return -$tzo->getOffset($dt);
 227      } else {
 228          if (isset($TZ)) return $TZ;
 229          $y = date('Y');
 230          $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y);
 231      }
 232      
 233      return $TZ;
 234  }
 235  
 236  /**
 237      Returns an array with date info.
 238  */
 239  function adodb_getdate($d=false,$fast=false)
 240  {
 241      if ($d === false) return getdate();
 242      if (!defined('ADODB_TEST_DATES')) {
 243          if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
 244              if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
 245                  return @getdate($d);
 246          }
 247      }
 248      return _adodb_getdate($d);
 249  }
 250  
 251  $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
 252  $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
 253  
 254  /**
 255      Low-level function that returns the getdate() array. We have a special
 256      $fast flag, which if set to true, will return fewer array values,
 257      and is much faster as it does not calculate dow, etc.
 258  */
 259  function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)
 260  {
 261  static $YRS;
 262  global $_month_table_normal,$_month_table_leaf;
 263  
 264      $d =  $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd));
 265      $_day_power = 86400;
 266      $_hour_power = 3600;
 267      $_min_power = 60;
 268      
 269      if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction 
 270      
 271      $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
 272      $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
 273      
 274      $d366 = $_day_power * 366;
 275      $d365 = $_day_power * 365;
 276      
 277      if ($d < 0) {
 278          
 279          if (empty($YRS)) $YRS = array(
 280              1970 => 0,
 281              1960 => -315619200,
 282              1950 => -631152000,
 283              1940 => -946771200,
 284              1930 => -1262304000,
 285              1920 => -1577923200,
 286              1910 => -1893456000,
 287              1900 => -2208988800,
 288              1890 => -2524521600,
 289              1880 => -2840140800,
 290              1870 => -3155673600,
 291              1860 => -3471292800,
 292              1850 => -3786825600,
 293              1840 => -4102444800,
 294              1830 => -4417977600,
 295              1820 => -4733596800,
 296              1810 => -5049129600,
 297              1800 => -5364662400,
 298              1790 => -5680195200,
 299              1780 => -5995814400,
 300              1770 => -6311347200,
 301              1760 => -6626966400,
 302              1750 => -6942499200,
 303              1740 => -7258118400,
 304              1730 => -7573651200,
 305              1720 => -7889270400,
 306              1710 => -8204803200,
 307              1700 => -8520336000,
 308              1690 => -8835868800,
 309              1680 => -9151488000,
 310              1670 => -9467020800,
 311              1660 => -9782640000,
 312              1650 => -10098172800,
 313              1640 => -10413792000,
 314              1630 => -10729324800,
 315              1620 => -11044944000,
 316              1610 => -11360476800,
 317              1600 => -11676096000);
 318  
 319          if ($is_gmt) $origd = $d;
 320          // The valid range of a 32bit signed timestamp is typically from 
 321          // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT
 322          //
 323          
 324          # old algorithm iterates through all years. new algorithm does it in
 325          # 10 year blocks
 326          
 327          /*
 328          # old algo
 329          for ($a = 1970 ; --$a >= 0;) {
 330              $lastd = $d;
 331              
 332              if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
 333              else $d += $d365;
 334              
 335              if ($d >= 0) {
 336                  $year = $a;
 337                  break;
 338              }
 339          }
 340          */
 341          
 342          $lastsecs = 0;
 343          $lastyear = 1970;
 344          foreach($YRS as $year => $secs) {
 345              if ($d >= $secs) {
 346                  $a = $lastyear;
 347                  break;
 348              }
 349              $lastsecs = $secs;
 350              $lastyear = $year;
 351          }
 352          
 353          $d -= $lastsecs;
 354          if (!isset($a)) $a = $lastyear;
 355          
 356          //echo ' yr=',$a,' ', $d,'.';
 357          
 358          for (; --$a >= 0;) {
 359              $lastd = $d;
 360              
 361              if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
 362              else $d += $d365;
 363              
 364              if ($d >= 0) {
 365                  $year = $a;
 366                  break;
 367              }
 368          }
 369          /**/
 370          
 371          $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd;
 372          
 373          $d = $lastd;
 374          $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
 375          for ($a = 13 ; --$a > 0;) {
 376              $lastd = $d;
 377              $d += $mtab[$a] * $_day_power;
 378              if ($d >= 0) {
 379                  $month = $a;
 380                  $ndays = $mtab[$a];
 381                  break;
 382              }
 383          }
 384          
 385          $d = $lastd;
 386          $day = $ndays + ceil(($d+1) / ($_day_power));
 387  
 388          $d += ($ndays - $day+1)* $_day_power;
 389          $hour = floor($d/$_hour_power);
 390      
 391      } else {
 392          for ($a = 1970 ;; $a++) {
 393              $lastd = $d;
 394              
 395              if ($leaf = _adodb_is_leap_year($a)) $d -= $d366;
 396              else $d -= $d365;
 397              if ($d < 0) {
 398                  $year = $a;
 399                  break;
 400              }
 401          }
 402          $secsInYear = $lastd;
 403          $d = $lastd;
 404          $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
 405          for ($a = 1 ; $a <= 12; $a++) {
 406              $lastd = $d;
 407              $d -= $mtab[$a] * $_day_power;
 408              if ($d < 0) {
 409                  $month = $a;
 410                  $ndays = $mtab[$a];
 411                  break;
 412              }
 413          }
 414          $d = $lastd;
 415          $day = ceil(($d+1) / $_day_power);
 416          $d = $d - ($day-1) * $_day_power;
 417          $hour = floor($d /$_hour_power);
 418      }
 419      
 420      $d -= $hour * $_hour_power;
 421      $min = floor($d/$_min_power);
 422      $secs = $d - $min * $_min_power;
 423      if ($fast) {
 424          return array(
 425          'seconds' => $secs,
 426          'minutes' => $min,
 427          'hours' => $hour,
 428          'mday' => $day,
 429          'mon' => $month,
 430          'year' => $year,
 431          'yday' => floor($secsInYear/$_day_power),
 432          'leap' => $leaf,
 433          'ndays' => $ndays
 434          );
 435      }
 436      
 437      
 438      $dow = adodb_dow($year,$month,$day);
 439  
 440      return array(
 441          'seconds' => $secs,
 442          'minutes' => $min,
 443          'hours' => $hour,
 444          'mday' => $day,
 445          'wday' => $dow,
 446          'mon' => $month,
 447          'year' => $year,
 448          'yday' => floor($secsInYear/$_day_power),
 449          'weekday' => gmdate('l',$_day_power*(3+$dow)),
 450          'month' => gmdate('F',mktime(0,0,0,$month,2,1971)),
 451          0 => $origd
 452      );
 453  }
 454  
 455  function adodb_tz_offset($gmt,$isphp5)
 456  {
 457      $zhrs = abs($gmt)/3600;
 458      $hrs = floor($zhrs);
 459      if ($isphp5) 
 460          return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); 
 461      else
 462          return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); 
 463      break;
 464  }
 465  
 466  
 467  function adodb_gmdate($fmt,$d=false)
 468  {
 469      return adodb_date($fmt,$d,true);
 470  }
 471  
 472  // accepts unix timestamp and iso date format in $d
 473  function adodb_date2($fmt, $d=false, $is_gmt=false)
 474  {
 475      if ($d !== false) {
 476          if (!preg_match( 
 477              "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", 
 478              ($d), $rr)) return adodb_date($fmt,false,$is_gmt);
 479  
 480          if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt);
 481      
 482          // h-m-s-MM-DD-YY
 483          if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt);
 484          else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt);
 485      }
 486      
 487      return adodb_date($fmt,$d,$is_gmt);
 488  }
 489  
 490  
 491  /**
 492      Return formatted date based on timestamp $d
 493  */
 494  function adodb_date($fmt,$d=false,$is_gmt=false)
 495  {
 496  static $daylight;
 497  global $ADODB_DATETIME_CLASS;
 498  
 499      if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
 500      if (!defined('ADODB_TEST_DATES')) {
 501          if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
 502              if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
 503                  return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
 504  
 505          }
 506      }
 507      $_day_power = 86400;
 508      
 509      $arr = _adodb_getdate($d,true,$is_gmt);
 510      
 511      if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv');
 512      if ($daylight) adodb_daylight_sv($arr, $is_gmt);
 513      
 514      $year = $arr['year'];
 515      $month = $arr['mon'];
 516      $day = $arr['mday'];
 517      $hour = $arr['hours'];
 518      $min = $arr['minutes'];
 519      $secs = $arr['seconds'];
 520      
 521      $max = strlen($fmt);
 522      $dates = '';
 523      
 524      $isphp5 = PHP_VERSION >= 5;
 525      
 526      /*
 527          at this point, we have the following integer vars to manipulate:
 528          $year, $month, $day, $hour, $min, $secs
 529      */
 530      for ($i=0; $i < $max; $i++) {
 531          switch($fmt[$i]) {
 532          case 'T': 
 533              if ($ADODB_DATETIME_CLASS) {
 534                  $dt = new DateTime();
 535                  $dt->SetDate($year,$month,$day);
 536                  $dates .= $dt->Format('T');
 537              } else
 538                  $dates .= date('T');
 539              break;
 540          // YEAR
 541          case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
 542          case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
 543          
 544              // 4.3.11 uses '04 Jun 2004'
 545              // 4.3.8 uses  ' 4 Jun 2004'
 546              $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', '        
 547                  . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' ';
 548              
 549              if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour; 
 550              
 551              if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min;
 552              
 553              if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;
 554              
 555              $gmt = adodb_get_gmt_diff($year,$month,$day);
 556              
 557              $dates .= ' '.adodb_tz_offset($gmt,$isphp5);
 558              break;
 559              
 560          case 'Y': $dates .= $year; break;
 561          case 'y': $dates .= substr($year,strlen($year)-2,2); break;
 562          // MONTH
 563          case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
 564          case 'Q': $dates .= ($month+3)>>2; break;
 565          case 'n': $dates .= $month; break;
 566          case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
 567          case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
 568          // DAY
 569          case 't': $dates .= $arr['ndays']; break;
 570          case 'z': $dates .= $arr['yday']; break;
 571          case 'w': $dates .= adodb_dow($year,$month,$day); break;
 572          case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break;
 573          case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break;
 574          case 'j': $dates .= $day; break;
 575          case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break;
 576          case 'S': 
 577              $d10 = $day % 10;
 578              if ($d10 == 1) $dates .= 'st';
 579              else if ($d10 == 2 && $day != 12) $dates .= 'nd';
 580              else if ($d10 == 3) $dates .= 'rd';
 581              else $dates .= 'th';
 582              break;
 583              
 584          // HOUR
 585          case 'Z':
 586              $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff($year,$month,$day); break;
 587          case 'O': 
 588              $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day);
 589              
 590              $dates .= adodb_tz_offset($gmt,$isphp5);
 591              break;
 592              
 593          case 'H': 
 594              if ($hour < 10) $dates .= '0'.$hour; 
 595              else $dates .= $hour; 
 596              break;
 597          case 'h': 
 598              if ($hour > 12) $hh = $hour - 12; 
 599              else {
 600                  if ($hour == 0) $hh = '12'; 
 601                  else $hh = $hour;
 602              }
 603              
 604              if ($hh < 10) $dates .= '0'.$hh;
 605              else $dates .= $hh;
 606              break;
 607              
 608          case 'G': 
 609              $dates .= $hour;
 610              break;
 611              
 612          case 'g':
 613              if ($hour > 12) $hh = $hour - 12; 
 614              else {
 615                  if ($hour == 0) $hh = '12'; 
 616                  else $hh = $hour; 
 617              }
 618              $dates .= $hh;
 619              break;
 620          // MINUTES
 621          case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break;
 622          // SECONDS
 623          case 'U': $dates .= $d; break;
 624          case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break;
 625          // AM/PM
 626          // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
 627          case 'a':
 628              if ($hour>=12) $dates .= 'pm';
 629              else $dates .= 'am';
 630              break;
 631          case 'A':
 632              if ($hour>=12) $dates .= 'PM';
 633              else $dates .= 'AM';
 634              break;
 635          default:
 636              $dates .= $fmt[$i]; break;
 637          // ESCAPE
 638          case "\\": 
 639              $i++;
 640              if ($i < $max) $dates .= $fmt[$i];
 641              break;
 642          }
 643      }
 644      return $dates;
 645  }
 646  
 647  /**
 648      Returns a timestamp given a GMT/UTC time. 
 649      Note that $is_dst is not implemented and is ignored.
 650  */
 651  function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false)
 652  {
 653      return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true);
 654  }
 655  
 656  /**
 657      Return a timestamp given a local time. Originally by jackbbs.
 658      Note that $is_dst is not implemented and is ignored.
 659      
 660      Not a very fast algorithm - O(n) operation. Could be optimized to O(1).
 661      
 662      NOTE: returns time() when the year is > 9999
 663  */
 664  function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false) 
 665  {
 666      if (!defined('ADODB_TEST_DATES')) {
 667  
 668          if ($mon === false) {
 669              return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec);
 670          }
 671          
 672          // for windows, we don't check 1970 because with timezone differences, 
 673          // 1 Jan 1970 could generate negative timestamp, which is illegal
 674          $usephpfns = (1971 < $year && $year < 2038
 675              || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038)
 676              ); 
 677              
 678          
 679          if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false;
 680              
 681          if ($usephpfns) {
 682                  return $is_gmt ?
 683                      @gmmktime($hr,$min,$sec,$mon,$day,$year):
 684                      @mktime($hr,$min,$sec,$mon,$day,$year);
 685          }
 686      }
 687      
 688      $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$mon,$day);
 689  
 690      /*
 691      # disabled because some people place large values in $sec.
 692      # however we need it for $mon because we use an array...
 693      $hr = intval($hr);
 694      $min = intval($min);
 695      $sec = intval($sec);
 696      */
 697      $mon = intval($mon);
 698      $day = intval($day);
 699      $year = intval($year);
 700      
 701      
 702      $year = adodb_year_digit_check($year);
 703  
 704      if ($mon > 12) {
 705          $y = floor(($mon-1)/ 12);
 706          $year += $y;
 707          $mon -= $y*12;
 708      } else if ($mon < 1) {
 709          $y = ceil((1-$mon) / 12);
 710          $year -= $y;
 711          $mon += $y*12;
 712      }
 713      
 714      $_day_power = 86400;
 715      $_hour_power = 3600;
 716      $_min_power = 60;
 717      
 718      $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
 719      $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
 720      
 721      $_total_date = 0;
 722      if($year > 9999) {
 723          return time();
 724      } else if ($year >= 1970) {
 725          for ($a = 1970 ; $a <= $year; $a++) {
 726              $leaf = _adodb_is_leap_year($a);
 727              if ($leaf == true) {
 728                  $loop_table = $_month_table_leaf;
 729                  $_add_date = 366;
 730              } else {
 731                  $loop_table = $_month_table_normal;
 732                  $_add_date = 365;
 733              }
 734              if ($a < $year) { 
 735                  $_total_date += $_add_date;
 736              } else {
 737                  for($b=1;$b<$mon;$b++) {
 738                      $_total_date += $loop_table[$b];
 739                  }
 740              }
 741          }
 742          $_total_date +=$day-1;
 743          $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
 744      
 745      } else {
 746          for ($a = 1969 ; $a >= $year; $a--) {
 747              $leaf = _adodb_is_leap_year($a);
 748              if ($leaf == true) {
 749                  $loop_table = $_month_table_leaf;
 750                  $_add_date = 366;
 751              } else {
 752                  $loop_table = $_month_table_normal;
 753                  $_add_date = 365;
 754              }
 755              if ($a > $year) { $_total_date += $_add_date;
 756              } else {
 757                  for($b=12;$b>$mon;$b--) {
 758                      $_total_date += $loop_table[$b];
 759                  }
 760              }
 761          }
 762          $_total_date += $loop_table[$mon] - $day;
 763          
 764          $_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
 765          $_day_time = $_day_power - $_day_time;
 766          $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different);
 767          if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction
 768          else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582.
 769      } 
 770      //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret;
 771      return $ret;
 772  }
 773  
 774  function adodb_gmstrftime($fmt, $ts=false)
 775  {
 776      return adodb_strftime($fmt,$ts,true);
 777  }
 778  
 779  // hack - convert to adodb_date
 780  function adodb_strftime($fmt, $ts=false,$is_gmt=false)
 781  {
 782  global $ADODB_DATE_LOCALE;
 783  
 784      if (!defined('ADODB_TEST_DATES')) {
 785          if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
 786              if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer
 787                  return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts);
 788  
 789          }
 790      }
 791      
 792      if (empty($ADODB_DATE_LOCALE)) {
 793      /*
 794          $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am
 795          $sep = substr($tstr,2,1);
 796          $hasAM = strrpos($tstr,'M') !== false;
 797      */
 798          # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24
 799          $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am
 800          $sep = substr($dstr,2,1);
 801          $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am
 802          $hasAM = strrpos($tstr,'M') !== false;
 803          
 804          $ADODB_DATE_LOCALE = array();
 805          $ADODB_DATE_LOCALE[] =  strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y';    
 806          $ADODB_DATE_LOCALE[]  = ($hasAM) ? 'h:i:s a' : 'H:i:s';
 807              
 808      }
 809      $inpct = false;
 810      $fmtdate = '';
 811      for ($i=0,$max = strlen($fmt); $i < $max; $i++) {
 812          $ch = $fmt[$i];
 813          if ($ch == '%') {
 814              if ($inpct) {
 815                  $fmtdate .= '%';
 816                  $inpct = false;
 817              } else
 818                  $inpct = true;
 819          } else if ($inpct) {
 820          
 821              $inpct = false;
 822              switch($ch) {
 823              case '0':
 824              case '1':
 825              case '2':
 826              case '3':
 827              case '4':
 828              case '5':
 829              case '6':
 830              case '7':
 831              case '8':
 832              case '9':
 833              case 'E':
 834              case 'O':
 835                  /* ignore format modifiers */
 836                  $inpct = true; 
 837                  break;
 838                  
 839              case 'a': $fmtdate .= 'D'; break;
 840              case 'A': $fmtdate .= 'l'; break;
 841              case 'h':
 842              case 'b': $fmtdate .= 'M'; break;
 843              case 'B': $fmtdate .= 'F'; break;
 844              case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break;
 845              case 'C': $fmtdate .= '\C?'; break; // century
 846              case 'd': $fmtdate .= 'd'; break;
 847              case 'D': $fmtdate .= 'm/d/y'; break;
 848              case 'e': $fmtdate .= 'j'; break;
 849              case 'g': $fmtdate .= '\g?'; break; //?
 850              case 'G': $fmtdate .= '\G?'; break; //?
 851              case 'H': $fmtdate .= 'H'; break;
 852              case 'I': $fmtdate .= 'h'; break;
 853              case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd
 854              case 'm': $fmtdate .= 'm'; break;
 855              case 'M': $fmtdate .= 'i'; break;
 856              case 'n': $fmtdate .= "\n"; break;
 857              case 'p': $fmtdate .= 'a'; break;
 858              case 'r': $fmtdate .= 'h:i:s a'; break;
 859              case 'R': $fmtdate .= 'H:i:s'; break;
 860              case 'S': $fmtdate .= 's'; break;
 861              case 't': $fmtdate .= "\t"; break;
 862              case 'T': $fmtdate .= 'H:i:s'; break;
 863              case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based
 864              case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based
 865              case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break;
 866              case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break;
 867              case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based
 868              case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based
 869              case 'y': $fmtdate .= 'y'; break;
 870              case 'Y': $fmtdate .= 'Y'; break;
 871              case 'Z': $fmtdate .= 'T'; break;
 872              }
 873          } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' ))
 874              $fmtdate .= "\\".$ch;
 875          else
 876              $fmtdate .= $ch;
 877      }
 878      //echo "fmt=",$fmtdate,"<br>";
 879      if ($ts === false) $ts = time();
 880      $ret = adodb_date($fmtdate, $ts, $is_gmt);
 881      return $ret;
 882  }
 883  
 884  ?>


Generated: Tue Oct 8 19:19:50 2013 Cross-referenced by PHPXref 0.7.1