| [ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 /** 3 * sfDateFormat class file. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the BSD License. 7 * 8 * Copyright(c) 2004 by Qiang Xue. All rights reserved. 9 * 10 * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue} 11 * The latest version of PRADO can be obtained from: 12 * {@link http://prado.sourceforge.net/} 13 * 14 * @author Wei Zhuo <weizhuo[at]gmail[dot]com> 15 * @version $Id: sfDateFormat.class.php 3409 2007-02-06 08:08:40Z fabien $ 16 * @package symfony 17 * @subpackage i18n 18 */ 19 20 /** 21 * Get the encoding utilities 22 */ 23 require_once(dirname(__FILE__).'/util.php'); 24 25 /** 26 * sfDateFormat class. 27 * 28 * The sfDateFormat class allows you to format dates and times with 29 * predefined styles in a locale-sensitive manner. Formatting times 30 * with the sfDateFormat class is similar to formatting dates. 31 * 32 * Formatting dates with the sfDateFormat class is a two-step process. 33 * First, you create a formatter with the getDateInstance method. 34 * Second, you invoke the format method, which returns a string containing 35 * the formatted date. 36 * 37 * DateTime values are formatted using standard or custom patterns stored 38 * in the properties of a DateTimeFormatInfo. 39 * 40 * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com> 41 * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004 42 * @package System.I18N.core 43 */ 44 class sfDateFormat 45 { 46 /** 47 * A list of tokens and their function call. 48 * @var array 49 */ 50 protected $tokens = array( 51 'G'=>'Era', 52 'y'=>'year', 53 'M'=>'mon', 54 'd'=>'mday', 55 'h'=>'Hour12', 56 'H'=>'hours', 57 'm'=>'minutes', 58 's'=>'seconds', 59 'E'=>'wday', 60 'D'=>'yday', 61 'F'=>'DayInMonth', 62 'w'=>'WeekInYear', 63 'W'=>'WeekInMonth', 64 'a'=>'AMPM', 65 'k'=>'HourInDay', 66 'K'=>'HourInAMPM', 67 'z'=>'TimeZone' 68 ); 69 70 /** 71 * A list of methods, to be used by the token function calls. 72 * @var array 73 */ 74 protected $methods = array(); 75 76 /** 77 * The sfDateTimeFormatInfo, containing culture specific patterns and names. 78 * @var sfDateTimeFormatInfo 79 */ 80 protected $formatInfo; 81 82 /** 83 * Initialize a new sfDateFormat. 84 * 85 * @param mixed either, null, a sfCultureInfo instance, a DateTimeFormatInfo instance, or a locale. 86 * @return sfDateFormat instance 87 */ 88 function __construct($formatInfo = null) 89 { 90 if (is_null($formatInfo)) 91 { 92 $this->formatInfo = sfDateTimeFormatInfo::getInvariantInfo(); 93 } 94 else if ($formatInfo instanceof sfCultureInfo) 95 { 96 $this->formatInfo = $formatInfo->DateTimeFormat; 97 } 98 else if ($formatInfo instanceof sfDateTimeFormatInfo) 99 { 100 $this->formatInfo = $formatInfo; 101 } 102 else 103 { 104 $this->formatInfo = sfDateTimeFormatInfo::getInstance($formatInfo); 105 } 106 107 $this->methods = get_class_methods($this); 108 } 109 110 /** 111 * Guesses a date without calling strtotime. 112 * 113 * @author Olivier Verdier <Olivier.Verdier@gmail.com> 114 * @param mixed the time as integer or string in strtotime format. 115 * @param string the input pattern; default is sql date or timestamp 116 * @return array same array as the getdate function 117 */ 118 public function getDate($time, $pattern = null) 119 { 120 if (is_null($time)) 121 { 122 return null; 123 } 124 125 // if the type is not a php timestamp 126 $isString = (string) $time !== (string) (int) $time; 127 128 if ($isString) 129 { 130 if (!$pattern) 131 { 132 if (strlen($time) == 10) 133 { 134 $pattern = 'i'; 135 } 136 else // otherwise, default: 137 { 138 $pattern = 'I'; 139 } 140 } 141 142 $pattern = $this->getPattern($pattern); 143 $tokens = $this->getTokens($pattern); 144 $pregPattern = ''; 145 $matchNames = array(); 146 foreach ($tokens as $token) 147 { 148 if ($matchName = $this->getFunctionName($token)) 149 { 150 $pregPattern .= '(\d+)'; 151 $matchNames[] = $matchName; 152 } 153 else 154 { 155 $pregPattern .= '[^\d]+'; 156 } 157 } 158 preg_match('@'.$pregPattern.'@', $time, $matches); 159 160 array_shift($matches); 161 162 if (count($matchNames) == count($matches)) 163 { 164 $date = array_combine($matchNames, $matches); 165 // guess the date if input with two digits 166 if (strlen($date['year']) == 2) 167 { 168 $date['year'] = date('Y', mktime(0, 0, 0, 1, 1, $date['year'])); 169 } 170 $date = array_map('intval', $date); 171 } 172 } 173 174 // the last attempt has failed we fall back on the default method 175 if (!isset($date)) 176 { 177 if ($isString) 178 { 179 $numericalTime = @strtotime($time); 180 if ($numericalTime === false) 181 { 182 throw new sfException(sprintf('Impossible to parse date "%s" with format "%s"', $time, $pattern)); 183 } 184 } 185 else 186 { 187 $numericalTime = $time; 188 } 189 $date = @getdate($numericalTime); 190 } 191 192 // we set default values for the time 193 foreach (array('hours', 'minutes', 'seconds') as $timeDiv) 194 { 195 if (!isset($date[$timeDiv])) 196 { 197 $date[$timeDiv] = 0; 198 } 199 } 200 201 return $date; 202 } 203 204 /** 205 * Format a date according to the pattern. 206 * 207 * @param mixed the time as integer or string in strtotime format. 208 * @return string formatted date time. 209 */ 210 public function format($time, $pattern = 'F', $inputPattern = null, $charset = 'UTF-8') 211 { 212 $date = $this->getDate($time, $inputPattern); 213 214 if (is_null($pattern)) 215 { 216 $pattern = 'F'; 217 } 218 219 $pattern = $this->getPattern($pattern); 220 $tokens = $this->getTokens($pattern); 221 222 for ($i = 0, $max = count($tokens); $i < $max; $i++) 223 { 224 $pattern = $tokens[$i]; 225 if ($pattern{0} == "'" && $pattern{strlen($pattern) - 1} == "'") 226 { 227 $tokens[$i] = str_replace('``````', '\'', preg_replace('/(^\')|(\'$)/', '', $pattern)); 228 } 229 else if ($pattern == '``````') 230 { 231 $tokens[$i] = '\''; 232 } 233 else 234 { 235 $function = ucfirst($this->getFunctionName($pattern)); 236 if ($function != null) 237 { 238 $fName = 'get'.$function; 239 if (in_array($fName, $this->methods)) 240 { 241 $tokens[$i] = $this->$fName($date, $pattern); 242 } 243 else 244 { 245 throw new sfException('function '.$function.' not found.'); 246 } 247 } 248 } 249 } 250 251 return I18N_toEncoding(implode('', $tokens), $charset); 252 } 253 254 /** 255 * For a particular token, get the corresponding function to call. 256 * 257 * @param string token 258 * @return mixed the function if good token, null otherwise. 259 */ 260 protected function getFunctionName($token) 261 { 262 if (isset($this->tokens[$token{0}])) 263 { 264 return $this->tokens[$token{0}]; 265 } 266 } 267 268 /** 269 * Get the pattern from DateTimeFormatInfo or some predefined patterns. 270 * If the $pattern parameter is an array of 2 element, it will assume 271 * that the first element is the date, and second the time 272 * and try to find an appropriate pattern and apply 273 * DateTimeFormatInfo::formatDateTime 274 * See the tutorial documentation for futher details on the patterns. 275 * 276 * @param mixed a pattern. 277 * @return string a pattern. 278 * @see DateTimeFormatInfo::formatDateTime() 279 */ 280 public function getPattern($pattern) 281 { 282 if (is_array($pattern) && count($pattern) == 2) 283 { 284 return $this->formatInfo->formatDateTime($this->getPattern($pattern[0]), $this->getPattern($pattern[1])); 285 } 286 287 switch ($pattern) 288 { 289 case 'd': 290 return $this->formatInfo->ShortDatePattern; 291 break; 292 case 'D': 293 return $this->formatInfo->LongDatePattern; 294 break; 295 case 'p': 296 return $this->formatInfo->MediumDatePattern; 297 break; 298 case 'P': 299 return $this->formatInfo->FullDatePattern; 300 break; 301 case 't': 302 return $this->formatInfo->ShortTimePattern; 303 break; 304 case 'T': 305 return $this->formatInfo->LongTimePattern; 306 break; 307 case 'q': 308 return $this->formatInfo->MediumTimePattern; 309 break; 310 case 'Q': 311 return $this->formatInfo->FullTimePattern; 312 break; 313 case 'f': 314 return $this->formatInfo->formatDateTime($this->formatInfo->LongDatePattern, $this->formatInfo->ShortTimePattern); 315 break; 316 case 'F': 317 return $this->formatInfo->formatDateTime($this->formatInfo->LongDatePattern, $this->formatInfo->LongTimePattern); 318 break; 319 case 'g': 320 return $this->formatInfo->formatDateTime($this->formatInfo->ShortDatePattern, $this->formatInfo->ShortTimePattern); 321 break; 322 case 'G': 323 return $this->formatInfo->formatDateTime($this->formatInfo->ShortDatePattern, $this->formatInfo->LongTimePattern); 324 break; 325 case 'i': 326 return 'yyyy-MM-dd'; 327 break; 328 case 'I': 329 return 'yyyy-MM-dd HH:mm:ss'; 330 break; 331 case 'M': 332 case 'm': 333 return 'MMMM dd'; 334 break; 335 case 'R': 336 case 'r': 337 return 'EEE, dd MMM yyyy HH:mm:ss'; 338 break; 339 case 's': 340 return 'yyyy-MM-ddTHH:mm:ss'; 341 break; 342 case 'u': 343 return 'yyyy-MM-dd HH:mm:ss z'; 344 break; 345 case 'U': 346 return 'EEEE dd MMMM yyyy HH:mm:ss'; 347 break; 348 case 'Y': 349 case 'y': 350 return 'yyyy MMMM'; 351 break; 352 default : 353 return $pattern; 354 } 355 } 356 357 /** 358 * Returns an easy to parse input pattern 359 * yy is replaced by yyyy and h by H 360 * 361 * @param string pattern. 362 * @return string input pattern 363 */ 364 public function getInputPattern($pattern) 365 { 366 $pattern = $this->getPattern($pattern); 367 368 $pattern = strtr($pattern, array('yyyy' => 'Y', 'h'=>'H', 'z'=>'', 'a'=>'')); 369 $pattern = strtr($pattern, array('yy'=>'yyyy', 'Y'=>'yyyy')); 370 371 return trim($pattern); 372 } 373 374 /** 375 * Tokenize the pattern. The tokens are delimited by group of 376 * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'. 377 * Any substrings, starting and ending with a single quote (') 378 * will be treated as a single token. 379 * 380 * @param string pattern. 381 * @return array string tokens in an array. 382 */ 383 protected function getTokens($pattern) 384 { 385 $char = null; 386 $tokens = array(); 387 $token = null; 388 389 $text = false; 390 391 for ($i = 0, $max = strlen($pattern); $i < $max; $i++) 392 { 393 if ($char == null || $pattern{$i} == $char || $text) 394 { 395 $token .= $pattern{$i}; 396 } 397 else 398 { 399 $tokens[] = str_replace("''", "'", $token); 400 $token = $pattern{$i}; 401 } 402 403 if ($pattern{$i} == "'" && $text == false) 404 { 405 $text = true; 406 } 407 else if ($text && $pattern{$i} == "'" && $char == "'") 408 { 409 $text = true; 410 } 411 else if ($text && $char != "'" && $pattern{$i} == "'") 412 { 413 $text = false; 414 } 415 416 $char = $pattern{$i}; 417 418 } 419 $tokens[] = $token; 420 421 return $tokens; 422 } 423 424 // makes a unix date from our incomplete $date array 425 protected function getUnixDate($date) 426 { 427 return getdate(mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year'])); 428 } 429 430 /** 431 * Get the year. 432 * "yy" will return the last two digits of year. 433 * "yyyy" will return the full integer year. 434 * 435 * @param array getdate format. 436 * @param string a pattern. 437 * @return string year 438 */ 439 protected function getYear($date, $pattern = 'yyyy') 440 { 441 $year = $date['year']; 442 switch ($pattern) 443 { 444 case 'yy': 445 return substr($year, 2); 446 case 'yyyy': 447 return $year; 448 default: 449 throw new sfException('The pattern for year is either "yy" or "yyyy".'); 450 } 451 } 452 453 /** 454 * Get the month. 455 * "M" will return integer 1 through 12 456 * "MM" will return the narrow month name, e.g. "J" 457 * "MMM" will return the abrreviated month name, e.g. "Jan" 458 * "MMMM" will return the month name, e.g. "January" 459 * 460 * @param array getdate format. 461 * @param string a pattern. 462 * @return string month name 463 */ 464 protected function getMon($date, $pattern = 'M') 465 { 466 $month = $date['mon']; 467 468 switch ($pattern) 469 { 470 case 'M': 471 return $month; 472 case 'MM': 473 return str_pad($month, 2, '0', STR_PAD_LEFT); 474 case 'MMM': 475 return $this->formatInfo->AbbreviatedMonthNames[$month - 1]; 476 break; 477 case 'MMMM': 478 return $this->formatInfo->MonthNames[$month - 1]; 479 default: 480 throw new sfException('The pattern for month is "M", "MM", "MMM", or "MMMM".'); 481 } 482 } 483 484 /** 485 * Get the day of the week. 486 * "E" will return integer 0 (for Sunday) through 6 (for Saturday). 487 * "EE" will return the narrow day of the week, e.g. "M" 488 * "EEE" will return the abrreviated day of the week, e.g. "Mon" 489 * "EEEE" will return the day of the week, e.g. "Monday" 490 * 491 * @param array getdate format. 492 * @param string a pattern. 493 * @return string day of the week. 494 */ 495 protected function getWday($date, $pattern = 'EEEE') 496 { 497 // if the $date comes from our home-made get date 498 if (!isset($date['wday'])) 499 { 500 $date = $this->getUnixDate($date); 501 } 502 $day = $date['wday']; 503 504 switch ($pattern) 505 { 506 case 'E': 507 return $day; 508 break; 509 case 'EE': 510 return $this->formatInfo->NarrowDayNames[$day]; 511 case 'EEE': 512 return $this->formatInfo->AbbreviatedDayNames[$day]; 513 break; 514 case 'EEEE': 515 return $this->formatInfo->DayNames[$day]; 516 break; 517 default: 518 throw new sfException('The pattern for day of the week is "E", "EE", "EEE", or "EEEE".'); 519 } 520 } 521 522 /** 523 * Get the day of the month. 524 * "d" for non-padding, "dd" will always return 2 characters. 525 * 526 * @param array getdate format. 527 * @param string a pattern. 528 * @return string day of the month 529 */ 530 protected function getMday($date, $pattern = 'd') 531 { 532 $day = $date['mday']; 533 534 switch ($pattern) 535 { 536 case 'd': 537 return $day; 538 case 'dd': 539 return str_pad($day, 2, '0', STR_PAD_LEFT); 540 case 'dddd': 541 return $this->getWday($date); 542 default: 543 throw new sfException('The pattern for day of the month is "d", "dd" or "dddd".'); 544 } 545 } 546 547 /** 548 * Get the era. i.e. in gregorian, year > 0 is AD, else BC. 549 * 550 * @todo How to support multiple Eras?, e.g. Japanese. 551 * @param array getdate format. 552 * @param string a pattern. 553 * @return string era 554 */ 555 protected function getEra($date, $pattern = 'G') 556 { 557 if ($pattern != 'G') 558 { 559 throw new sfException('The pattern for era is "G".'); 560 } 561 562 return $this->formatInfo->getEra($date['year'] > 0 ? 1 : 0); 563 } 564 565 /** 566 * Get the hours in 24 hour format, i.e. [0-23]. 567 * "H" for non-padding, "HH" will always return 2 characters. 568 * 569 * @param array getdate format. 570 * @param string a pattern. 571 * @return string hours in 24 hour format. 572 */ 573 protected function getHours($date, $pattern = 'H') 574 { 575 $hour = $date['hours']; 576 577 switch ($pattern) 578 { 579 case 'H': 580 return $hour; 581 case 'HH': 582 return str_pad($hour, 2, '0', STR_PAD_LEFT); 583 default: 584 throw new sfException('The pattern for 24 hour format is "H" or "HH".'); 585 } 586 } 587 588 /** 589 * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM. 590 * 591 * @param array getdate format. 592 * @param string a pattern. 593 * @return string AM or PM designator 594 */ 595 protected function getAMPM($date, $pattern = 'a') 596 { 597 if ($pattern != 'a') 598 { 599 throw new sfException('The pattern for AM/PM marker is "a".'); 600 } 601 602 return $this->formatInfo->AMPMMarkers[intval($date['hours'] / 12)]; 603 } 604 605 /** 606 * Get the hours in 12 hour format. 607 * "h" for non-padding, "hh" will always return 2 characters. 608 * 609 * @param array getdate format. 610 * @param string a pattern. 611 * @return string hours in 12 hour format. 612 */ 613 protected function getHour12($date, $pattern = 'h') 614 { 615 $hour = $date['hours']; 616 $hour = ($hour == 12 | $hour == 0) ? 12 : ($hour) % 12; 617 618 switch ($pattern) 619 { 620 case 'h': 621 return $hour; 622 case 'hh': 623 return str_pad($hour, 2, '0', STR_PAD_LEFT); 624 default: 625 throw new sfException('The pattern for 24 hour format is "H" or "HH".'); 626 } 627 } 628 629 /** 630 * Get the minutes. 631 * "m" for non-padding, "mm" will always return 2 characters. 632 * 633 * @param array getdate format. 634 * @param string a pattern. 635 * @return string minutes. 636 */ 637 protected function getMinutes($date, $pattern = 'm') 638 { 639 $minutes = $date['minutes']; 640 641 switch ($pattern) 642 { 643 case 'm': 644 return $minutes; 645 case 'mm': 646 return str_pad($minutes, 2, '0', STR_PAD_LEFT); 647 default: 648 throw new sfException('The pattern for minutes is "m" or "mm".'); 649 } 650 } 651 652 /** 653 * Get the seconds. 654 * "s" for non-padding, "ss" will always return 2 characters. 655 * 656 * @param array getdate format. 657 * @param string a pattern. 658 * @return string seconds 659 */ 660 protected function getSeconds($date, $pattern = 's') 661 { 662 $seconds = $date['seconds']; 663 664 switch ($pattern) 665 { 666 case 's': 667 return $seconds; 668 case 'ss': 669 return str_pad($seconds, 2, '0', STR_PAD_LEFT); 670 default: 671 throw new sfException('The pattern for seconds is "s" or "ss".'); 672 } 673 } 674 675 /** 676 * Get the timezone from the server machine. 677 * 678 * @todo How to get the timezone for a different region? 679 * @param array getdate format. 680 * @param string a pattern. 681 * @return string time zone 682 */ 683 protected function getTimeZone($date, $pattern = 'z') 684 { 685 if ($pattern != 'z') 686 { 687 throw new sfException('The pattern for time zone is "z".'); 688 } 689 690 return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year'])); 691 } 692 693 /** 694 * Get the day in the year, e.g. [1-366] 695 * 696 * @param array getdate format. 697 * @param string a pattern. 698 * @return int hours in AM/PM format. 699 */ 700 protected function getYday($date, $pattern = 'D') 701 { 702 if ($pattern != 'D') 703 { 704 throw new sfException('The pattern for day in year is "D".'); 705 } 706 707 return $date['yday']; 708 } 709 710 /** 711 * Get day in the month. 712 * 713 * @param array getdate format. 714 * @param string a pattern. 715 * @return int day in month 716 */ 717 protected function getDayInMonth($date, $pattern = 'FF') 718 { 719 switch ($pattern) 720 { 721 case 'F': 722 return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])); 723 break; 724 case 'FF': 725 return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])); 726 break; 727 default: 728 throw new sfException('The pattern for day in month is "F" or "FF".'); 729 } 730 } 731 732 /** 733 * Get the week in the year. 734 * 735 * @param array getdate format. 736 * @param string a pattern. 737 * @return int week in year 738 */ 739 protected function getWeekInYear($date, $pattern = 'w') 740 { 741 if ($pattern != 'w') 742 { 743 throw new sfException('The pattern for week in year is "w".'); 744 } 745 746 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])); 747 } 748 749 /** 750 * Get week in the month. 751 * 752 * @param array getdate format. 753 * @return int week in month 754 */ 755 protected function getWeekInMonth($date, $pattern = 'W') 756 { 757 if ($pattern != 'W') 758 { 759 throw new sfException('The pattern for week in month is "W".'); 760 } 761 762 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year'])); 763 } 764 765 /** 766 * Get the hours [1-24]. 767 * 768 * @param array getdate format. 769 * @param string a pattern. 770 * @return int hours [1-24] 771 */ 772 protected function getHourInDay($date, $pattern = 'k') 773 { 774 if ($pattern != 'k') 775 { 776 throw new sfException('The pattern for hour in day is "k".'); 777 } 778 779 return $date['hours'] + 1; 780 } 781 782 /** 783 * Get the hours in AM/PM format, e.g [1-12] 784 * 785 * @param array getdate format. 786 * @param string a pattern. 787 * @return int hours in AM/PM format. 788 */ 789 protected function getHourInAMPM($date, $pattern = 'K') 790 { 791 if ($pattern != 'K') 792 { 793 throw new sfException('The pattern for hour in AM/PM is "K".'); 794 } 795 796 return ($date['hours'] + 1) % 12; 797 } 798 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |