| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
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 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |