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