[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/date/date_php4/ -> date_php4.inc (source)

   1  <?php
   2  // $Id: date_php4.inc,v 1.27.4.41 2010/08/13 10:50:52 karens Exp $
   3  
   4  /**
   5   * @file
   6   *
   7   * PHP 5 Date and Timezone function substitutions for PHP 4.
   8   * Replicates some PHP 5 timezone functions and procedures.
   9   * Not all PHP 5 functions have equivalents.
  10   *
  11   * Simpletest tests are provided to use with Simpletest module.
  12   *
  13   * Supported:
  14   *   date_create()
  15   *     with limitations, input date must be one of:
  16   *       - YYYY-MM-DD HH:MM:SS
  17   *       - YYYY-MM-DDTHH:MM:SS
  18   *       - 'now'
  19   *       - unix timestamp prefixed with '@', like '@99999999'
  20   *       - or something strtotime will understand (only for dates later than 1970).
  21   *     also must supply timezone as second argument to date_create().
  22   *   date_modify()
  23   *     with limitations, must supply modification in form like:
  24   *       '+1 day|week|month|year|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday'
  25   *       '-3 day|week|month|year|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday'
  26   *   date_format()
  27   *   date_date_set()
  28   *   date_timezone_set()
  29   *   date_offset_get()
  30   *   date_timezone_get()
  31   *   timezone_offset_get()
  32   *   timezone_name_get()
  33   *   timezone_open()
  34   *   timezone_abbreviations_list()
  35   *   timezone_identifiers_list()
  36   *
  37   * Not supported:
  38   *   timezone_ transitions_ get()
  39   *    - we just don't have all those historical transitions available in PHP 4
  40   */
  41  if (!function_exists('date_create')) {
  42  /**
  43   *  PHP 4 equivalent for date_create().
  44   *
  45   *  @param string $date_in
  46   *    - 'now' or empty
  47   *    - anything strtotime will support for a post-1970 date,
  48   *    - a timestamp (must be prefixed with a @ to be interpreted as a
  49   *        timestamp in PHP 5 -- see http://bugs.php.net/bug.php?id=40171)
  50   *    - otherwise, must be a DATETIME date (YYYY-MM-DD HH:MM:SS) or
  51   *        ISO date (YYYY-MM-DDTHH:MM:SS)
  52   *        PHP 5 accepts more alternative formats, but that's too complicated
  53   *        for us to handle here, so a standardized format is required.
  54   *
  55   *  @param string $timezone
  56   *    PHP 5 uses a timezone object, in PHP 4 use a timezone name.
  57   *  @return object
  58   *    Returns and object structured like:
  59   *      Object =>
  60   *        value => '2007-04-15 09:25'
  61   *        timezone => 'UTC'
  62   */
  63    function date_create($date_in = NULL, $timezone = NULL) {
  64      if (empty($date_in) || strtolower($date_in) == 'now') {
  65        // Create a current date for an empty value or 'now'.
  66        $date_out = date_date('Y-m-d H:i:s', (time()), $timezone);
  67      }
  68      elseif (substr($date_in, 0, 1) == '@' && is_numeric(substr($date_in, 1))) {
  69        // An number prefixed with '@' is interpreted as a timestamp.
  70        $date_out = date_date('Y-m-d H:i', substr($date_in, 1), $timezone);
  71      }
  72      elseif (preg_match(DATE_REGEX_LOOSE, $date_in, $regs)) {
  73        $year = date_pad(isset($regs[1]) ? $regs[1] : 0, 4);
  74        $month = date_pad(isset($regs[2]) ? $regs[2] : 0);
  75        $day = date_pad(isset($regs[3]) ? $regs[3] : 0);
  76        $hour = date_pad(isset($regs[5]) ? $regs[5] : 0);
  77        $minute = date_pad(isset($regs[6]) ? $regs[6] : 0);
  78        $second = date_pad(isset($regs[7]) ? $regs[7] : 0);
  79        $date_out = "$year-$month-$day $hour:$minute:$second";
  80      }
  81      else {
  82        // Try to use strtotime, will only work on post-1970 dates.
  83        // Only use it if the value is big enough that timezone conversions
  84        // won't make it into a negative value.
  85        $test = @strtotime($date_in .' '. $timezone);
  86        if ($test > 86400) {
  87          $date_out = date_date('Y-m-d H:i', $test, $timezone);
  88        }
  89      }
  90      if (empty($date_out)) {
  91        return NULL;
  92      }
  93      $date = new StdClass();
  94      $date->value = $date_out;
  95      $date->timestamp = date_datetime2timestamp($date->value, $timezone);
  96      $date->timezone = $timezone;
  97      return $date;
  98    }
  99  }
 100  
 101  if (!function_exists('date_format')) {
 102    require_once('./'. drupal_get_path('module', 'date_php4') .'/date_php4_calc.inc');
 103  /**
 104   * PHP 4 equivalent for date_format().
 105   *
 106   * Some formats that work in PHP 5 won't work in PHP 4, many won't work for
 107   * dates earlier than 1970. Filter out those that need special treatment.
 108   * No translation done here because the PHP 5 date_format() function isn't
 109   * doing any translation and we need to return identical values in both.
 110   *
 111   * @param object $date
 112   * @param string $format
 113   * @return string
 114   *   return formatted date
 115   */
 116    function date_format($date, $format) {
 117      $php5_formats = array('N', 'o', 'e', 'P', 'c', '\\');
 118      $timestamp = $date->timestamp;
 119      $date_string = '';
 120      $max = strlen($format);
 121      for ($i = 0; $i < $max; $i++) {
 122        $c = $format[$i];
 123        if ($date->timezone == 'UTC' && abs($timestamp) <= 0x7FFFFFFF && !in_array($c, $php5_formats)) {
 124          $date_string .= gmdate($c, $timestamp);
 125        }
 126        else{
 127          switch ($c) {
 128            case 'U':
 129              $date_string .= $timestamp;
 130              break;
 131            case 'l':
 132            case 'w':
 133            case 'D':
 134              $dow = date_dow(date_part_extract($date->value, 'day'),
 135                date_part_extract($date->value, 'month'),
 136                date_part_extract($date->value, 'year'));
 137              if ($c == 'w') {
 138                $date_string .= $dow;
 139              }
 140              elseif ($c == 'l') {
 141                $days = date_week_days_untranslated();
 142                $date_string .= $days[$dow];
 143              }
 144              elseif ($c == 'D') {
 145                // There is no date_week_days_abbr_untranslated(). 
 146                // This rule works for English, untranslated day names.
 147                $days = date_week_days_abbr();
 148                $date_string .= substr($days[$dow], 0, 3);
 149              }
 150              break;
 151            case 'L':
 152              $date_string .= date_is_leap_year(date_part_extract($date->value, 'year'));
 153              break;
 154            case 'z':
 155              $date_string .= date_calc_julian_date(date_part_extract($date->value, 'day'),
 156              date_part_extract($date->value, 'month'),
 157              date_part_extract($date->value, 'year'));
 158              break;
 159            case 'N':
 160              $w = date_date('w', $timestamp, $date->timezone);
 161              $date_string .= $w != 0 ? $w : 7;
 162              break;
 163            case 'o':
 164              $iso_week = date_calc_gregorian_to_ISO(date_part_extract($date->value, 'day'),
 165                date_part_extract($date->value, 'month'),
 166                date_part_extract($date->value, 'year'));
 167              $iso = explode('-', $iso_week);
 168              $date_string .= ($c == 'o') ? $iso[0] : $iso[1];
 169              break;
 170            case 'O':
 171              $date_string .= sprintf('%s%02d%02d', (date_offset_get($date) < 0 ? '-' : '+'), abs(date_offset_get($date) / 3600), abs(date_offset_get($date) % 3600) / 60);
 172              break;
 173            case 'P':
 174              $date_string .= sprintf('%s%02d:%02d', (date_offset_get($date) < 0 ? '-' : '+'), abs(date_offset_get($date) / 3600), abs(date_offset_get($date) % 3600) / 60);
 175              break;
 176            case 'e':
 177              $date_string .= $date->timezone;
 178              break;
 179            case 'Z':
 180              $date_string .= date_offset_get($date);
 181              break;
 182            case '\\':
 183              $date_string .= $format[++$i];
 184              break;
 185            case 't':
 186              $date_string .= date_calc_days_in_month(date_part_extract($date->value, 'month'),
 187                date_part_extract($date->value, 'year'));
 188              break;
 189            case 'W':
 190              $result = date_calc_gregorian_to_ISO(date_part_extract($date->value, 'day'),
 191                date_part_extract($date->value, 'month'),
 192                date_part_extract($date->value, 'year'));
 193              $result = explode('-', $result);  
 194              $date_string .= $result[1];  
 195            default:
 196              if (strpos('AaeDFlMTBcdGgHhIijLmNnOoPrSstUuwYyZz', $c) !== FALSE) {
 197                $date_string .= date_date($c, $timestamp, $date->timezone);
 198              }
 199              else {
 200                $date_string .= $c;
 201              }
 202          }
 203        }
 204      }
 205      return $date_string;
 206    }
 207  }
 208  
 209  /**
 210   *  PHP 4 equivalent for date_date_set().
 211   *
 212   *  @param $date
 213   *    a date object returned by date_create().
 214   *  @param $year
 215   *    a new year.
 216   *  @param $month
 217   *    a new month.
 218   *  @param $day
 219   *    a new day.
 220   *  @return $date
 221   *    the date objected updated for the new timezone.
 222   *
 223   */
 224  if (!function_exists('date_date_set')) {
 225    function date_date_set(&$date, $year, $month, $day) {
 226      $new_date = substr_replace($date->value, date_pad($year, 4), 0, 4);
 227      $new_date = substr_replace($new_date, date_pad($month), 5, 2);
 228      $new_date = substr_replace($new_date, date_pad($day), 8, 2);
 229      $date = date_create($new_date, $date->timezone);
 230      return $date;
 231    }
 232  }
 233  
 234  /**
 235   *  PHP 4 equivalent for date_date_set().
 236   *
 237   *  @param $date
 238   *    a date object returned by date_create().
 239   *  @param $year
 240   *    a new year.
 241   *  @param $month
 242   *    a new month.
 243   *  @param $day
 244   *    a new day.
 245   *  @return $date
 246   *    the date objected updated for the new timezone.
 247   *
 248   */
 249  if (!function_exists('date_time_set')) {
 250    function date_time_set(&$date, $hour, $minute, $second) {
 251      $new_date = substr_replace($date->value, date_pad($hour), 11, 2);
 252      $new_date = substr_replace($new_date, date_pad($minute), 14, 2);
 253      $new_date = substr_replace($new_date, date_pad($second), 16, 2);
 254      $date = date_create($new_date, $date->timezone);
 255      return $date;
 256    }
 257  }
 258  
 259  if (!function_exists('date_timezone_set')) {
 260  /**
 261   *  PHP 4 equivalent for date_timezones_set().
 262   *
 263   *  @param $date
 264   *    a date object returned by date_create().
 265   *  @param $timezone
 266   *    a new timezone for the date object.
 267   *  @return $date
 268   *    the date objected updated for the new timezone.
 269   *
 270   */
 271    function date_timezone_set(&$date, $timezone) {
 272      $date->timezone = $timezone;
 273      $date->value = date_date(DATE_FORMAT_DATETIME, $date->timestamp, $timezone);
 274      return $date;
 275    }
 276  }
 277  
 278  if (!function_exists('timezone_open')) {
 279  /**
 280   *  PHP 4 equivalent for timezone_open().
 281   *   Just track the timezone name.
 282   */
 283    function timezone_open($timezone) {
 284      return $timezone;
 285    }
 286  }
 287  
 288  if (!function_exists('timezone_name_get')) {
 289  /**
 290   *  PHP 4 equivalent for timezone_name_get().
 291   */
 292    function timezone_name_get($timezone) {
 293      return $timezone;
 294    }
 295  }
 296  
 297  if (!function_exists('date_timezone_get')) {
 298  /**
 299   *  PHP 4 equivalent for date_timezone_get().
 300   */
 301    function date_timezone_get($date) {
 302      return $date->timezone;
 303    }
 304  }
 305  
 306  if (!function_exists('timezone_offset_get')) {
 307  /**
 308   *  PHP 4 equivalent for timezone_offset_get().
 309   *
 310   *  Cache results for expensive process of getting offsets for each timezone.
 311   *  Each cached timezone array will show whether the timezone has dst and the
 312   *  dst and non-dst offset for that timezone.
 313   *
 314   *  @param $timezone
 315   *    a timezone returned by timezone_open().
 316   *  @param $date
 317   *    a date object returned by date_create().
 318   *  @return $offset
 319   *    the offset in seconds for the supplied date object.
 320   */
 321    function timezone_offset_get($timezone, $date) {
 322      if (empty($timezone) || $timezone == 'UTC' || !date_timezone_is_valid($timezone)) {
 323        return 0;
 324      }
 325      static $zones = array(), $offsets = array();
 326      if (!in_array($timezone, $zones)) {
 327        $cached = cache_get('date_timezone_offsets:'. $timezone);
 328        $offsets[$timezone] = isset($cached->data) ? $cached->data : array();
 329        $zones[] = $timezone;
 330        if (empty($offsets[$timezone])) {
 331          $offsets[$timezone] = array('dst' => 0);
 332          $zones = timezone_abbreviations_list();
 333          foreach ($zones as $key => $abbr) {
 334            foreach ($abbr as $zone) {
 335              if ($zone['timezone_id'] == $timezone && $zone['dst'] == 1 && !isset($offsets[$timezone]['dst_offset'])) {
 336                $offsets[$timezone]['dst_offset'] = $zone['offset'];
 337                $offsets[$timezone]['dst'] = 1;
 338              }
 339              elseif ($zone['timezone_id'] == $timezone && $zone['dst'] != 1 && !isset($offsets[$timezone]['offset'])) {
 340                $offsets[$timezone]['offset'] = $zone['offset'];
 341              }
 342            }
 343          }
 344          cache_set('date_timezone_offsets:'. $timezone, $offsets[$timezone]);
 345        }
 346      }
 347      $timestamp = $date->timestamp;
 348      if ($offsets[$timezone]['dst'] == 1) {
 349        if (date_is_dst($timestamp, $timezone, $offsets[$timezone]['dst'])) {
 350          return $offsets[$timezone]['dst_offset'];
 351        }
 352      }
 353      return $offsets[$timezone]['offset'];
 354    }
 355  }
 356  
 357  if (!function_exists('date_offset_get')) {
 358  /**
 359   *  PHP 4 equivalent for date_offset_get().
 360   *
 361   *  Cache results for expensive process of getting offsets for each timezone.
 362   *  Each cached timezone array will show whether the timezone has dst and the
 363   *  dst and non-dst offset for that timezone.
 364   *
 365   *  @param $date
 366   *    a date object returned by date_create().
 367   *  @return $offset
 368   *    the offset in seconds for the supplied date object.
 369   */
 370    function date_offset_get($date) {
 371      return timezone_offset_get(timezone_open($date->timezone), $date);
 372    }
 373  }
 374  
 375  if (!function_exists('date_modify')) {
 376    require_once('./'. drupal_get_path('module', 'date_php4') .'/date_php4_calc.inc');
 377  /**
 378   * A limited set of options are provided here to modify dates.
 379   * Uses strtotime() on dates after 1970. Uses date_php4_calc.inc to do
 380   * calculations on older dates.
 381   *
 382   * Will work for things like date_modify($date, '+1 Sunday');
 383   *
 384   * @param $date
 385   *   a date object created by date_create() to use as a reference
 386   *   point for the calculation.
 387   * @param $change
 388   *   something like following phrases:
 389   *     '+1 day|week|month|year|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday'
 390   *     '-3 day|week|month|year|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday'
 391   *
 392   * @return
 393   *   the date that matches the phrase.
 394   *
 395   */
 396    function date_modify(&$date, $change) { 
 397      $cdate = $date->value;
 398      $time = substr($date->value, 11, 8);
 399     
 400      // We have to use strings like 'First Sunday' instead of
 401      // +1 Sunday to overcome a PHP5 bug (see #369020).
 402      // Swap those values out here and go back to '+1 Sunday',
 403      // the code that works in PHP4.
 404      $replace = array_flip(date_order());
 405      $change = strtr($change, $replace);
 406      
 407      $change = trim($change);   
 408      //Date is too old for strtotime(), or looking for custom +/- values, use date_calc instead.
 409      if (substr($change, 0, 1) != '+' && substr($change, 0, 1) != '-'
 410      && 1971 < date_part_extract($cdate, 'year')
 411      && date_part_extract($cdate, 'year') < 2038) {
 412        $cdate = strtotime($change, strtotime($cdate .' UTC'));
 413        // strtotime will sometimes end up with a bogus adjustment for daylight
 414        // savings time, so compute the date and force them time back to the original.
 415        $date->value = substr_replace(date_date(DATE_FORMAT_DATETIME, $cdate, $date->timezone), $time, 11);
 416      }
 417      else {
 418        $days = date_week_days_untranslated();
 419        $dows = array_flip($days);
 420        preg_match('/([+|-])\s?([0-9]{1,32})\s?([day(s)?|week(s)?|month(s)?|year(s)?|hour(s)?|minute(s)?|second(s)?|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday]{1,10})/', $change, $results);
 421        $direction = $results[1];
 422        $count = $results[2];
 423        $item = $results[3];
 424        if (empty($results) || empty($item)) {
 425          return;
 426        }
 427        if (substr($item, -1) == 's') {
 428          $item = substr($item, 0, strlen($item) - 1);
 429        }
 430        // Process +/- Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday
 431        if (in_array($item, $days)) {
 432          $dow = $dows[$item];
 433          if ($direction == '+') {
 434            $function = 'date_calc_next_day_of_week';
 435          }
 436          else {
 437            $function = 'date_calc_prev_day_of_week';
 438          }
 439          for ($i = 1; $i <= $count; $i++) {
 440            $cdate = $function($dow,
 441              date_part_extract($cdate, 'day'),
 442              date_part_extract($cdate, 'month'),
 443              date_part_extract($cdate, 'year'));
 444          }
 445          $date->value = $cdate .' '. $time;
 446        }
 447        elseif ($item == 'day') {
 448          if ($direction == '+') {
 449            $function = 'date_calc_next_day';
 450          }
 451          else {
 452            $function = 'date_calc_prev_day';
 453          }
 454          for ($i = 1; $i <= $count; $i++) {
 455            $cdate = $function(date_part_extract($cdate, 'day'),
 456              date_part_extract($cdate, 'month'),
 457              date_part_extract($cdate, 'year'));
 458          }
 459          $date->value = $cdate .' '. $time;
 460        }
 461        elseif ($item == 'month') {
 462          if ($direction == '+') {
 463            $function = 'date_calc_begin_of_month_by_span';
 464          }
 465          else {
 466            $function = 'date_calc_end_of_month_by_span';
 467          }
 468          // Find the next end or beginning of month that matches the search.
 469          $day = date_part_extract($cdate, 'day');
 470          $cdate = $function($direction . $count, date_part_extract($cdate, 'month'), date_part_extract($cdate, 'year'));
 471          // Construct a new date with the current day of the month and the new month and year.
 472          $mon = date_part_extract($cdate, 'month');
 473          $year = date_part_extract($cdate, 'year');
 474          $date->value = date_pad($year, 4) .'-'. date_pad($mon) .'-'. date_pad($day) .' '. $time;
 475        }
 476        elseif ($item == 'week') {
 477          $dow = date_day_of_week($date);
 478          if ($direction == '+') {
 479            $function = 'date_calc_begin_of_next_week';
 480          }
 481          else {
 482            $function = 'date_calc_begin_of_prev_week';
 483          }
 484          // Move to right week.
 485          for ($i = 1; $i <= $count; $i++) {
 486            $cdate = $function(date_part_extract($cdate, 'day'),
 487              date_part_extract($cdate, 'month'),
 488              date_part_extract($cdate, 'year'));
 489          }
 490          // Move to the right day of the week, if we're not looking for the first day.
 491          if ($dow != variable_get('date_first_day', 1)) {
 492            for ($i = 1; $i <= $dow; $i++) {
 493              $cdate = date_calc_next_day(date_part_extract($cdate, 'day'),
 494                date_part_extract($cdate, 'month'),
 495                date_part_extract($cdate, 'year'));
 496            }
 497          }
 498          $date->value = $cdate .' '. $time;
 499        }
 500        elseif ($item == 'year') {
 501          // Move to the new year.
 502          $year = date_part_extract($cdate, 'year');
 503          for ($i = 1; $i <= $count; $i++) {
 504            if ($direction == '+') {
 505              $year++;
 506            }
 507            else {
 508              $year--;
 509            }
 510          }
 511          // Construct a new date with the current day and month and the new year.
 512          $day = date_part_extract($cdate, 'day');
 513          $mon = date_part_extract($cdate, 'month');
 514          $date->value = date_pad($year, 4) .'-'. date_pad($mon) .'-'. date_pad($day) .' '. $time;
 515        }
 516        else {
 517          switch ($item) {
 518            case 'hour':
 519              $count = $count * 3600;
 520              break;
 521            case 'minute':
 522              $count = $count * 60;
 523              break;
 524          }
 525          switch ($direction) {
 526            case '-':
 527              $timestamp = $date->timestamp - $count;
 528              break;
 529            default:
 530              $timestamp = $date->timestamp + $count;
 531          }
 532          $date->value = date_date('Y-m-d H:i:s', $timestamp, $date->timezone);
 533        }
 534      }
 535      $date->timestamp = date_datetime2timestamp($date->value, $date->timezone);
 536      return $date;
 537    }
 538  }
 539  
 540  if (!function_exists('timezone_identifiers_list')) {
 541  /**
 542   * PHP 4 equivalent for timezone_identifiers_list().
 543   *
 544   * Expanded array looks like:
 545   * array(
 546   *   0 => 'Africa/Abidjan',
 547   *   1 => 'Africa/Accra',
 548   *   2 => 'Africa/Addis_Ababa',
 549   *   ...
 550   */
 551    function timezone_identifiers_list() {
 552      static $timezone_identifiers_list = array();
 553      if (empty($timezone_identifiers_list)) {
 554        include(drupal_get_path('module', 'date_php4') .'/date_php4_tz_identifiers.inc');
 555      }
 556      return $timezone_identifiers_list;
 557    }
 558  }
 559  
 560  if (!function_exists('timezone_abbreviations_list')) {
 561  /**
 562   * PHP 4 equivalent for timezone_abbreviations_list().
 563   *   Array keyed on timezone abbreviation.
 564   *
 565   * Expanded array looks like:
 566   * array(
 567   *   'cdt' => array (
 568   *     0 => array (
 569   *      'dst' => true,
 570   *      'offset' => -18000,
 571   *      'timezone_id' => 'America/Chicago',
 572   *     ),
 573   *     1 => array (
 574   *      'dst' => true,
 575   *      'offset' => -14400,
 576   *      'timezone_id' => 'America/Havana',
 577   *     )...
 578   *
 579   */
 580    function timezone_abbreviations_list() {
 581      static $timezone_abbreviations_list = array();
 582      if (empty($timezone_abbreviations_list)) {
 583        include(drupal_get_path('module', 'date_php4') .'/date_php4_tz_abbreviations_list.inc');
 584      }
 585      return $timezone_abbreviations_list;
 586    }
 587  }
 588  
 589  /**
 590   * Create a timestamp from a datetime value.
 591   *
 592   * Can't use date_convert() to turn datetime to unix within the
 593   * PHP 4 emulation  because it creates endless loops.
 594   */
 595  function date_datetime2timestamp($datetime, $timezone) {
 596    preg_match(DATE_REGEX_LOOSE, $datetime, $regs);
 597    return date_mktime((isset($regs[5]) ? $regs[5] : 0), (isset($regs[6]) ? $regs[6] : 0), (isset($regs[7]) ? $regs[7] : 0), (isset($regs[2]) ? $regs[2] : 0), (isset($regs[3]) ? $regs[3] : 0), (isset($regs[1]) ? $regs[1] : 0), $timezone);
 598  }
 599  
 600  /**
 601   * Check if time is in Daylight Savings Time
 602   *   Uses dst region code, as stored in the $timezone_map array
 603   *   from date_php4_tz_map.inc
 604   *
 605   * @param $timezone name
 606   * @param $timestamp
 607   * @return
 608   *   0 or 1
 609   */
 610  function date_is_dst($timestamp, $timezone = NULL) {
 611    if (abs($timestamp) > 0x7FFFFFFF) {
 612      return FALSE;
 613    }
 614    if (empty($timezone)) {
 615      $timezone = date_default_timezone_name();
 616    }
 617    
 618    static $timezone_map = array();
 619    if (empty($timezone_map)) {
 620      include(drupal_get_path('module', 'date_php4') .'/date_php4_tz_map.inc');
 621    }
 622    $region = array_key_exists($timezone, $timezone_map) ? $timezone_map[$timezone]['dst_region'] : 0;
 623             
 624    // This should really be done with date_date() to get the right timezone
 625    // adjustment for the year, but that leads to circular code that won't
 626    // work, so we're stuck with date(), which hopefully will create the right
 627    // year in most cases.
 628    $year = date('Y', $timestamp);
 629  
 630    // Information on Daylight Saving time was obtained from http://webexhibits.org/daylightsaving/g.html
 631    // Note that 'last sunday' is interpreted as 'the last sunday before...'.
 632    switch ($region) {
 633      case 0:
 634        return 0;
 635      case 1: // Egypt
 636        // start of DST (last Friday in April)
 637        $dststart = strtotime("last friday UTC", strtotime("1 may $year UTC"));
 638        // end of DST (last Thursday in September)
 639        $dstend = strtotime("last thursday UTC", strtotime("1 october $year UTC"));
 640        break;
 641      case 2: // Namibia
 642        // start of DST (first Sunday in September)
 643        $dststart = strtotime("first sunday UTC", strtotime("1 september $year UTC"));
 644        // end of DST (first Sunday April)
 645        $dstend = strtotime("first sunday UTC", strtotime("1 april $year UTC"));
 646        break;
 647      case 3: // Former USSR
 648        // start of DST (last Sunday in March)
 649        $dststart = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 650        // end of DST (last Sunday October)
 651        $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 652        break;
 653      case 4: // Iraq, Syria
 654        // start of DST (April 1st)
 655        $dststart = strtotime("1 april $year UTC");
 656        // end of DST (October 1st)
 657        $dstend = strtotime("1 october $year UTC");
 658        break;
 659      case 5: // Israel
 660        // start of DST (last Friday befor April 2nd, 2am)
 661        $dststart = strtotime("-1 week friday GMT", strtotime("2 april $year GMT")) + 7200;
 662        // end of DST (last sunday before 10th of tishray. see http://cgate.co.il/navigation/shaon_kaiz.htm.
 663        switch ($year) {
 664          case '2007':
 665            $dstend = strtotime("-1 sunday GMT", strtotime("16 september $year GMT"))+ 7200;
 666            break;
 667          case '2008':
 668            $dstend = strtotime("-1 sunday GMT",strtotime("9 october $year GMT"))+7200;
 669            break;
 670          case '2009':
 671            $dstend = strtotime("-1 sunday GMT", strtotime("28 september $year GMT"))+ 7200;
 672            break;
 673          case '2010':
 674            $dstend = strtotime("-1 sunday GMT", strtotime("18 september $year GMT"))+ 7200;
 675            break;
 676          case '2011':
 677            $dstend = strtotime("-1 sunday GMT", strtotime("8 october $year GMT"))+ 7200;
 678            break;
 679          case '2012':
 680            $dstend = strtotime("-1 sunday GMT", strtotime("26 september $year GMT"))+ 7200;
 681            break;
 682          case '2013':
 683            $dstend = strtotime("-1 sunday GMT", strtotime("14 september $year GMT"))+ 7200;
 684            break;
 685          case '2014':
 686            $dstend = strtotime("-1 sunday GMT", strtotime("4 october $year GMT"))+ 7200;
 687            break;
 688          case '2015':
 689            $dstend = strtotime("-1 sunday GMT", strtotime("23 september $year GMT"))+ 7200;
 690            break;
 691          case '2016':
 692            $dstend = strtotime("-1 sunday GMT", strtotime("12 october $year GMT"))+ 7200;
 693            break;
 694          default:
 695            return false;
 696        }
 697        break;
 698      case 6: // Lebanon, Kirgizstan
 699        // start of DST (Last Sunday in March)
 700        $dststart = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 701        // end of DST (Last Sunday in October)
 702        $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 703        break;
 704      case 7: // Palestine
 705        // start of DST (First Friday on or after April 15th)
 706        $dststart = strtotime("next friday UTC", strtotime("14 april $year UTC"));
 707        // end of DST (First Friday on or after October 15th)
 708        $dstend = strtotime("next friday UTC", strtotime("14 october $year UTC"));
 709        break;
 710      case 8: // Iran
 711        // start of DST (the first day of Farvardin (March 21))
 712        $dststart = strtotime("21 march $year UTC");
 713        // end of DST (the first day of Mehr (September 23))
 714        $dstend = strtotime("23 september $year UTC");
 715        break;
 716      case 9: // South Australia
 717        // start of DST  (last Sunday in October)
 718        $dststart = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 719        // end of DST (last Sunday in March)
 720        $dstend = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 721        break;
 722      case 10: // Australia, Tasmania
 723        // start of DST  (first Sunday in October)
 724        $dststart = strtotime("first sunday UTC", strtotime("1 october $year UTC"));
 725        // end of DST (last Sunday in March)
 726        $dstend = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 727        break;
 728      case 11: // New Zealand
 729        // start of DST  (first Sunday in October)
 730        $dststart = strtotime("first sunday UTC", strtotime("1 october $year UTC"));
 731        // end of DST (first Sunday in April)
 732        $dstend = strtotime("first sunday UTC", strtotime("1 april $year UTC"));
 733        break;
 734      case 12: // Tonga
 735        // start of DST (first Sunday in November)
 736        $dststart = strtotime("first sunday UTC",  strtotime("1 november $year UTC"));
 737        // end of DST (last Sunday in January)
 738        $dstend = strtotime("last sunday UTC", strtotime("1 february $year UTC"));
 739        break;
 740      case 13: // EU and other European countries
 741        // start of DST (last Sunday in March 1 am UTC)
 742        $dststart = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 743        // end of DST in Europe (last Sunday in October 1 am UTC)
 744        $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 745        break;
 746      case 14: // Russian Federation
 747        // start of DST (last Sunday in March 2 am local time)
 748        $dststart = strtotime("last sunday UTC", strtotime("1 april $year UTC"));
 749        // end of DST (last Sunday in October 2 am local time)
 750        $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 751        break;
 752      case 15: // Northern America (where applicable)
 753        // start of DST  (where applicable) (first Sunday in April before 2007,
 754        // after that second Sunday in March, 2 am local time)
 755        if ($year < 2007) {
 756          $dststart = strtotime("first sunday UTC", strtotime("1 april $year UTC"));
 757        }
 758        else {
 759          $dststart = strtotime("second sunday UTC", strtotime("1 march $year UTC"));
 760        }
 761        // end of DST (where applicable) (last Sunday in October 2 am local time)
 762        if ($year < 2007) {
 763          $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 764        }
 765        else {
 766          $dstend = strtotime("first sunday UTC", strtotime("1 november $year UTC"));
 767        }
 768        break;
 769      case 16: // Cuba
 770        // start of DST  (April 1st)
 771        $dststart = strtotime("1 april $year UTC");
 772        // end of DST (last Sunday in October)
 773        $dstend = strtotime("last sunday UTC", strtotime("1 november $year UTC"));
 774        break;
 775      case 17: // Brazil
 776        // start of DST  (first Sunday in November)
 777        $dststart = strtotime("first sunday UTC", strtotime("1 november $year UTC"));
 778        // end of DST (third Sunday in February)
 779        $dstend = strtotime("third sunday UTC", strtotime("1 february $year UTC"));
 780        break;
 781      case 18: // Chile
 782        // start of DST  (Second Saturday of October - at midnight)
 783        $dststart = strtotime("second saturday UTC", strtotime("1 october $year UTC"));
 784        // end of DST (Second Saturday of March - at midnight)
 785        $dstend = strtotime("second sunday UTC", strtotime("1 march $year UTC"));
 786        break;
 787      case 19: // Falklands
 788        // start of DST  (First Sunday on or after 8 September)
 789        $dststart = strtotime("next sunday UTC", strtotime("7 september $year UTC"));
 790        // end of DST (First Sunday on or after 6 April)
 791        $dstend = strtotime("next sunday UTC", strtotime("5 april $year UTC"));
 792        break;
 793      case 20: // Paraguay
 794        // start of DST  (first Sunday in September)
 795        $dststart = strtotime("first sunday UTC", strtotime("1 september $year UTC"));
 796        // end of DST (first Sunday in April)
 797        $dstend = strtotime("first sunday UTC", strtotime("1 april $year UTC"));
 798        break;
 799    }
 800    // Have to use reverse logic in southern hemisphere.
 801    $southern = array(9, 10, 11, 12, 17, 18, 19, 20);
 802    if (in_array($region, $southern)) {
 803      return !($timestamp <= $dststart && $dstend <= $timestamp);
 804    }
 805    else {
 806      return ($dststart <= $timestamp && $timestamp <= $dstend);
 807    }
 808  }
 809  
 810  /**
 811   * @ingroup adodb
 812   * @{
 813   */
 814  /**
 815   * Functions to handle mktime(), date(), and getdate() for dates outside the
 816   * normal range. Uses native php date functions when possible, alterate
 817   * methods when native functions won't work.
 818   *
 819   * Without these functions date(), mktime(), and getdate() won't work on
 820   * dates prior to 1970 in PHP 4 or on dates prior to 1901 in PHP 5.
 821   *
 822   * Replace native php functions:
 823   *   getdate() with date_getdate()
 824   *   date() with date_date()
 825   *   gmdate() with date_gmdate()
 826   *   mktime() with date_mktime()
 827   *   gmmktime() with gmdate_mktime()
 828   *
 829   * Note: Dates earlier than 1582 need a Gregorian correction applied, which
 830   * works correctly if only applied once. If the same early date is run through
 831   * these functions more than once, the Gregorian correction may get duplicated
 832   * or undone and not work correctly.
 833   *
 834   * The solution in PHP 5 is to use date_create() and date_format() for very old
 835   * dates, which will correctly handle that adjustment. There is no foolproof
 836   * workaround for PHP 4. PHP 5 date_create() and date_format() functions
 837   * will also handle dates earlier than 100.
 838   *
 839   * The following functions were derived from code obtained from
 840   * http://phplens.com/phpeverywhere/adodb_date_library, licensed as follows:
 841   *
 842   * COPYRIGHT(c) 2003-2005 John Lim
 843   * All rights reserved.
 844   *
 845   * Redistribution and use in source and binary forms, with or without
 846   * modification, are permitted under the terms of the BSD License.
 847   *
 848   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 849   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 850   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 851   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 852   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 853   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 854   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 855   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 856   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 857   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 858   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 859   * POSSIBILITY OF SUCH DAMAGE.
 860  */
 861  
 862  require_once('./'. drupal_get_path('module', 'date_php4') .'/date_php4_lib.inc');
 863  
 864  /**
 865   * Returns an array with date info.
 866   *
 867   * @param $timestamp
 868   *   A unix timestamp.
 869   * @param $timezone name
 870   *   Use 'UTC' to avoid timezone conversion.
 871   */
 872  function date_getdate($timestamp = false, $timezone = false) {
 873    return _date_getdate($timestamp, $timezone);
 874  }
 875  
 876  /**
 877   * Like date_getdate with no GMT conversion.
 878   */
 879  function date_gmgetdate($timestamp = false) {
 880    if (!$timestamp) return array();
 881    $array    = date_getdate($timestamp, 'UTC');
 882    $array[0] = $timestamp;
 883    return $array;
 884  }
 885  
 886  /**
 887   * Return formatted date based on timestamp $timestamp.
 888   *
 889   * @param $format
 890   *   the format to be used for the returned timestamp
 891   * @param $timestamp
 892   *   a unix timestamp
 893   * @param $timezone name
 894   *   Use 'UTC' to avoid timezone conversion.
 895   */
 896  function date_date($format, $timestamp = false, $timezone = false) {
 897    // date($format) will adjust to the server timezone, which may
 898    // not be right, but we don't use it in this module anywhere and 
 899    // there is no easy way to get it working right without creating 
 900    // circular code.
 901    if ($timestamp === false) return ($is_gmt)? @gmdate($format): @date($format);
 902    if ($timezone === FALSE) {
 903      $timezone = date_default_timezone_name();
 904    }
 905    // Anything with a timezone other than UTC needs to be forced to the
 906    // low level function to compute the timezone offset correctly.
 907    $is_gmt = $timezone == 'UTC' ? TRUE : FALSE;
 908    if (abs($timestamp) <= 0x7FFFFFFF) {
 909      // Below PHP 5.2 in windows, must be positive integer
 910      if ($timestamp >= 0 && $is_gmt) {
 911        return @gmdate($format, $timestamp);
 912      }
 913      elseif ($timestamp >= 0 && variable_get('date_use_server_zone', FALSE)) {
 914        return @date($format, $timestamp);
 915      }
 916    }
 917    return _date_date($format, $timestamp, $timezone);
 918  }
 919  
 920  /**
 921   * Like date_date with no GMT conversion.
 922   */
 923  function date_gmdate($format, $timestamp = false, $test = false) {
 924    return date_date($format, $timestamp, 'UTC', $test);
 925  }
 926  
 927  /**
 928   * Return a timestamp given a local time.
 929   * 
 930   * @param $timezone name
 931   *   Use 'UTC' to avoid timezone conversion.
 932   *
 933   * Force anything that will require timezone conversion to use
 934   * lower level functions to make sure we adjust to the right timezone
 935   * (native 'date' functions use the server timezone).
 936   */
 937  function date_mktime($hr, $min, $sec, $mon = false, $day = false, $year = false, $timezone = false) {
 938    if ($timezone === FALSE) {
 939      $timezone = date_default_timezone_name();
 940    }
 941    $is_gmt = $timezone == 'UTC' ? TRUE : FALSE;
 942    $hr = intval($hr);
 943    $min = intval($min);
 944    $sec = intval($sec);
 945    if ($mon === false && $is_gmt) {
 946      return @gmmktime($hr, $min, $sec);
 947    }
 948    $mon = intval($mon) > 0 ? intval($mon) : date('n');
 949    $day = intval($day) > 0 ? intval($day) : date('j');
 950    $year = intval($year) > 0 ? intval($year) : date('Y');
 951    
 952    // Don't use native handling for any values that could create negative
 953    // timestamp, Windows does not support them at all in PHP 4, and
 954    // the adodb date library notes that since RedHat 7.3, negative 
 955    // timestamps are not supported in glibc either.
 956    // Step in one year on either side of allowable 1970-2038 window
 957    // to be sure timezone adjustments and month and day additions
 958    // won't push our date outside this window.
 959    if (1971 < $year && $year < 2037 && $is_gmt) {
 960      return @gmmktime($hr, $min, $sec, $mon, $day, $year);
 961    }
 962    
 963    return _date_mktime($hr, $min, $sec, $mon, $day, $year, $timezone);
 964  }
 965  
 966  /**
 967   * Like date_mktime with no GMT conversion.
 968  */
 969  function date_gmmktime($hr, $min, $sec, $mon = false, $day = false, $year = false) {
 970    return date_mktime($hr, $min, $sec, $mon, $day, $year, 'UTC');
 971  }
 972  
 973  /**
 974   * Get local time zone offset from GMT.
 975   * 
 976   * @return timezone offset in seconds
 977   */
 978  function date_get_gmt_diff_ts($timestamp, $timezone = NULL) {
 979    if ($timezone == 'UTC') {
 980      return 0;
 981    }
 982    elseif (empty($timezone)) {
 983      $timezone = date_default_timezone_name();
 984    }
 985    $date = new StdClass();
 986    $date->timestamp = $timestamp;
 987    $date->timezone = $timezone;
 988    return date_offset_get($date);
 989  }
 990  
 991  
 992  /**
 993   * Fix 2-digit years. Works for any century. Assumes that if 2-digit is
 994   * more than 30 years in future, then previous century.
 995  */
 996  function date_year_digit_check($y) {
 997    if ($y < 100) {
 998      $yr = (integer) date("Y");
 999      $century = (integer) ($yr /100);
1000      if ($yr%100 > 50) {
1001        $c1 = $century + 1;
1002        $c0 = $century;
1003      } else {
1004        $c1 = $century;
1005        $c0 = $century - 1;
1006      }
1007      $c1 *= 100;
1008      // if 2-digit year is less than 30 years in future, set it to this century
1009      // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
1010      if (($y + $c1) < $yr + 30) $y = $y + $c1;
1011      else $y = $y + $c0 * 100;
1012    }
1013    return $y;
1014  }
1015  
1016  /**
1017   * Returns day of week for given date (0 = Sunday), works on dates outside
1018   * normal date range.
1019   *
1020   * Adapted from a function in the ADODB date library by John Lim, more info in
1021   * date_php4_lib.inc.
1022   *
1023   * @param int  $day
1024   * @param int  $month
1025   * @param int  $year
1026   * @return
1027   *    the number of the day in the week
1028   */
1029  function date_dow($day, $month, $year) {
1030    // Gregorian correction from ADODB
1031    if ($year <= 1582) {
1032      if ($year < 1582 ||
1033        ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
1034       else
1035        $greg_correction = 0;
1036    } else
1037      $greg_correction = 0;
1038    if($month > 2)
1039        $month -= 2;
1040    else {
1041        $month += 10;
1042        $year--;
1043    }
1044    $day = (floor((13 * $month - 1) / 5) +
1045      $day + ($year % 100) +
1046      floor(($year % 100) / 4) +
1047      floor(($year / 100) / 4) - 2 *
1048      floor($year / 100) + 77 + $greg_correction);
1049    $weekday_number = $day - 7 * floor($day / 7);
1050    return $weekday_number;
1051  }
1052  
1053  /**
1054   * Returns true for a leap year, else false. Works outside normal date range.
1055   *
1056   * @param int  $year
1057   * @return boolean
1058   */
1059  function date_is_leap_year($year) {
1060    if ($year < 1000) {
1061      return false;
1062    }
1063    if ($year < 1582) { // pre Gregorio XIII - 1582
1064      return ($year % 4 == 0);
1065    }
1066    else {  // post Gregorio XIII - 1582
1067      return (($year % 4 == 0) && ($year % 100 != 0)) || ($year % 400 == 0);
1068    }
1069  }
1070  
1071  /**
1072   * @} End of ingroup "datelib".
1073   */


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7