"Fossies" - the Fresh Open Source Software Archive

Member "yii-1.1.22.bf1d26/framework/i18n/CDateFormatter.php" (16 Jan 2020, 17268 Bytes) of package /linux/www/yii-1.1.22.bf1d26.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "CDateFormatter.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.21.733ac5_vs_1.1.22.bf1d26.

    1 <?php
    2 /**
    3  * CDateFormatter class file.
    4  *
    5  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
    6  * @author Qiang Xue <qiang.xue@gmail.com>
    7  * @link http://www.yiiframework.com/
    8  * @copyright 2008-2013 Yii Software LLC
    9  * @license http://www.yiiframework.com/license/
   10  */
   11 
   12 /**
   13  * CDateFormatter provides date/time localization functionalities.
   14  *
   15  * CDateFormatter allows you to format dates and times in a locale-sensitive manner.
   16  * Patterns are interpreted in the locale that the CDateFormatter instance
   17  * is associated with. For example, month names and weekday names may vary
   18  * under different locales, which yields different formatting results.
   19  * The patterns that CDateFormatter recognizes are as defined in
   20  * {@link http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns CLDR}.
   21  *
   22  * CDateFormatter supports predefined patterns as well as customized ones:
   23  * <ul>
   24  * <li>The method {@link formatDateTime()} formats date or time or both using
   25  *   predefined patterns which include 'full', 'long', 'medium' (default) and 'short'.</li>
   26  * <li>The method {@link format()} formats datetime using the specified pattern.
   27  *   See {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns} for
   28  *   details about the recognized pattern characters.</li>
   29  * </ul>
   30  *
   31  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
   32  * @author Qiang Xue <qiang.xue@gmail.com>
   33  * @package system.i18n
   34  * @since 1.0
   35  */
   36 class CDateFormatter extends CComponent
   37 {
   38     /**
   39      * @var array pattern characters mapping to the corresponding translator methods
   40      */
   41     private static $_formatters=array(
   42         'G'=>'formatEra',
   43         'y'=>'formatYear',
   44         'M'=>'formatMonth',
   45         'L'=>'formatMonth',
   46         'd'=>'formatDay',
   47         'h'=>'formatHour12',
   48         'H'=>'formatHour24',
   49         'm'=>'formatMinutes',
   50         's'=>'formatSeconds',
   51         'E'=>'formatDayInWeek',
   52         'c'=>'formatDayInWeek',
   53         'e'=>'formatDayInWeek',
   54         'D'=>'formatDayInYear',
   55         'F'=>'formatDayInMonth',
   56         'w'=>'formatWeekInYear',
   57         'W'=>'formatWeekInMonth',
   58         'a'=>'formatPeriod',
   59         'k'=>'formatHourInDay',
   60         'K'=>'formatHourInPeriod',
   61         'z'=>'formatTimeZone',
   62         'Z'=>'formatTimeZone',
   63         'v'=>'formatTimeZone',
   64     );
   65 
   66     private $_locale;
   67 
   68     /**
   69      * Constructor.
   70      * @param mixed $locale locale ID (string) or CLocale instance
   71      */
   72     public function __construct($locale)
   73     {
   74         if(is_string($locale))
   75             $this->_locale=CLocale::getInstance($locale);
   76         else
   77             $this->_locale=$locale;
   78     }
   79 
   80     /**
   81      * Formats a date according to a customized pattern.
   82      * @param string $pattern the pattern (See {@link http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns})
   83      * @param mixed $time UNIX timestamp or a string in strtotime format
   84      * @return string formatted date time. Null if $time is null. (the null value check is available since Yii 1.1.11)
   85      */
   86     public function format($pattern,$time)
   87     {
   88         if($time===null)
   89             return null;
   90 
   91         if(is_string($time))
   92         {
   93             if(ctype_digit($time) || ($time[0]=='-' && ctype_digit(substr($time, 1))))
   94                 $time=(int)$time;
   95             else
   96                 $time=strtotime($time);
   97         }
   98         $date=CTimestamp::getDate($time,false,false);
   99         $tokens=$this->parseFormat($pattern);
  100         foreach($tokens as &$token)
  101         {
  102             if(is_array($token)) // a callback: method name, sub-pattern
  103                 $token=$this->{$token[0]}($token[1],$date);
  104         }
  105         return implode('',$tokens);
  106     }
  107 
  108     /**
  109      * Formats a date according to a predefined pattern.
  110      * The predefined pattern is determined based on the date pattern width and time pattern width.
  111      * @param mixed $timestamp UNIX timestamp or a string in strtotime format
  112      * @param string $dateWidth width of the date pattern. It can be 'full', 'long', 'medium' and 'short'.
  113      * If null, it means the date portion will NOT appear in the formatting result
  114      * @param string $timeWidth width of the time pattern. It can be 'full', 'long', 'medium' and 'short'.
  115      * If null, it means the time portion will NOT appear in the formatting result
  116      * @return string formatted date time.
  117      */
  118     public function formatDateTime($timestamp,$dateWidth='medium',$timeWidth='medium')
  119     {
  120         if(!empty($dateWidth))
  121             $date=$this->format($this->_locale->getDateFormat($dateWidth),$timestamp);
  122 
  123         if(!empty($timeWidth))
  124             $time=$this->format($this->_locale->getTimeFormat($timeWidth),$timestamp);
  125 
  126         if(isset($date) && isset($time))
  127         {
  128             $dateTimePattern=$this->_locale->getDateTimeFormat();
  129             return strtr($dateTimePattern,array('{0}'=>$time,'{1}'=>$date));
  130         }
  131         elseif(isset($date))
  132             return $date;
  133         elseif(isset($time))
  134             return $time;
  135     }
  136 
  137     /**
  138      * Parses the datetime format pattern.
  139      * @param string $pattern the pattern to be parsed
  140      * @return array tokenized parsing result
  141      */
  142     protected function parseFormat($pattern)
  143     {
  144         static $formats=array();  // cache
  145         if(isset($formats[$pattern]))
  146             return $formats[$pattern];
  147         $tokens=array();
  148         $n=strlen($pattern);
  149         $isLiteral=false;
  150         $literal='';
  151         for($i=0;$i<$n;++$i)
  152         {
  153             $c=$pattern[$i];
  154             if($c==="'")
  155             {
  156                 if($i<$n-1 && $pattern[$i+1]==="'")
  157                 {
  158                     $tokens[]="'";
  159                     $i++;
  160                 }
  161                 elseif($isLiteral)
  162                 {
  163                     $tokens[]=$literal;
  164                     $literal='';
  165                     $isLiteral=false;
  166                 }
  167                 else
  168                 {
  169                     $isLiteral=true;
  170                     $literal='';
  171                 }
  172             }
  173             elseif($isLiteral)
  174                 $literal.=$c;
  175             else
  176             {
  177                 for($j=$i+1;$j<$n;++$j)
  178                 {
  179                     if($pattern[$j]!==$c)
  180                         break;
  181                 }
  182                 $p=str_repeat($c,$j-$i);
  183                 if(isset(self::$_formatters[$c]))
  184                     $tokens[]=array(self::$_formatters[$c],$p);
  185                 else
  186                     $tokens[]=$p;
  187                 $i=$j-1;
  188             }
  189         }
  190         if($literal!=='')
  191             $tokens[]=$literal;
  192 
  193         return $formats[$pattern]=$tokens;
  194     }
  195 
  196     /**
  197      * Get the year.
  198      * "yy" will return the last two digits of year.
  199      * "y...y" will pad the year with 0 in the front, e.g. "yyyyy" will generate "02008" for year 2008.
  200      * @param string $pattern a pattern.
  201      * @param array $date result of {@link CTimestamp::getdate}.
  202      * @return string formatted year
  203      */
  204     protected function formatYear($pattern,$date)
  205     {
  206         $year=$date['year'];
  207         if($pattern==='yy')
  208             return str_pad($year%100,2,'0',STR_PAD_LEFT);
  209         else
  210             return str_pad($year,strlen($pattern),'0',STR_PAD_LEFT);
  211     }
  212 
  213     /**
  214      * Get the month.
  215      * "M" will return integer 1 through 12;
  216      * "MM" will return two digits month number with necessary zero padding, e.g. 05;
  217      * "MMM" will return the abrreviated month name, e.g. "Jan";
  218      * "MMMM" will return the full month name, e.g. "January";
  219      * "MMMMM" will return the narrow month name, e.g. "J";
  220      * @param string $pattern a pattern.
  221      * @param array $date result of {@link CTimestamp::getdate}.
  222      * @throws CException if "month" pattern is unknown
  223      * @return string month name
  224      */
  225     protected function formatMonth($pattern,$date)
  226     {
  227         $month=$date['mon'];
  228         switch($pattern)
  229         {
  230             case 'M':
  231                 return $month;
  232             case 'MM':
  233                 return str_pad($month,2,'0',STR_PAD_LEFT);
  234             case 'MMM':
  235                 return $this->_locale->getMonthName($month,'abbreviated');
  236             case 'MMMM':
  237                 return $this->_locale->getMonthName($month,'wide');
  238             case 'MMMMM':
  239                 return $this->_locale->getMonthName($month,'narrow');
  240             case 'L':
  241                 return $month;
  242             case 'LL':
  243                 return str_pad($month,2,'0',STR_PAD_LEFT);
  244             case 'LLL':
  245                 return $this->_locale->getMonthName($month,'abbreviated', true);
  246             case 'LLLL':
  247                 return $this->_locale->getMonthName($month,'wide', true);
  248             case 'LLLLL':
  249                 return $this->_locale->getMonthName($month,'narrow', true);
  250             default:
  251                 throw new CException(Yii::t('yii','The pattern for month must be "M", "MM", "MMM", "MMMM", "L", "LL", "LLL" or "LLLL".'));
  252         }
  253     }
  254 
  255     /**
  256      * Get the day of the month.
  257      * "d" for non-padding, "dd" will always return 2 digits day numbers, e.g. 05.
  258      * @param string $pattern a pattern.
  259      * @param array $date result of {@link CTimestamp::getdate}.
  260      * @throws CException if "day" pattern is unknown
  261      * @return string day of the month
  262      */
  263     protected function formatDay($pattern,$date)
  264     {
  265         $day=$date['mday'];
  266         if($pattern==='d')
  267             return $day;
  268         elseif($pattern==='dd')
  269             return str_pad($day,2,'0',STR_PAD_LEFT);
  270         else
  271             throw new CException(Yii::t('yii','The pattern for day of the month must be "d" or "dd".'));
  272     }
  273 
  274     /**
  275      * Get the day in the year, e.g. [1-366]
  276      * @param string $pattern a pattern.
  277      * @param array $date result of {@link CTimestamp::getdate}.
  278      * @throws CException is "dayInYear" pattern is unknown
  279      * @return integer hours in AM/PM format.
  280      */
  281     protected function formatDayInYear($pattern,$date)
  282     {
  283         $day=$date['yday'];
  284         if(($n=strlen($pattern))<=3)
  285             return str_pad($day,$n,'0',STR_PAD_LEFT);
  286         else
  287             throw new CException(Yii::t('yii','The pattern for day in year must be "D", "DD" or "DDD".'));
  288     }
  289 
  290     /**
  291      * Get day of week in the month, e.g. 2nd Wed in July.
  292      * @param string $pattern a pattern.
  293      * @param array $date result of {@link CTimestamp::getdate}.
  294      * @throws CException if "dayInMonth" pattern is unknown
  295      * @return integer day in month
  296      * @see http://www.unicode.org/reports/tr35/#Date_Format_Patterns
  297      */
  298     protected function formatDayInMonth($pattern,$date)
  299     {
  300         if($pattern==='F')
  301             return (int)(($date['mday']+6)/7);
  302         else
  303             throw new CException(Yii::t('yii','The pattern for day in month must be "F".'));
  304     }
  305 
  306     /**
  307      * Get the day of the week.
  308      * "E", "EE", "EEE" will return abbreviated week day name, e.g. "Tues";
  309      * "EEEE" will return full week day name;
  310      * "EEEEE" will return the narrow week day name, e.g. "T";
  311      * @param string $pattern a pattern.
  312      * @param array $date result of {@link CTimestamp::getdate}.
  313      * @throws CException if "dayInWeek" pattern is unknown
  314      * @return string day of the week.
  315      * @see http://www.unicode.org/reports/tr35/#Date_Format_Patterns
  316      */
  317     protected function formatDayInWeek($pattern,$date)
  318     {
  319         $day=$date['wday'];
  320         switch($pattern)
  321         {
  322             case 'E':
  323             case 'EE':
  324             case 'EEE':
  325             case 'eee':
  326                 return $this->_locale->getWeekDayName($day,'abbreviated');
  327             case 'EEEE':
  328             case 'eeee':
  329                 return $this->_locale->getWeekDayName($day,'wide');
  330             case 'EEEEE':
  331             case 'eeeee':
  332                 return $this->_locale->getWeekDayName($day,'narrow');
  333             case 'e':
  334             case 'ee':
  335             case 'c':
  336                 return $day ? $day : 7;
  337             case 'ccc':
  338                 return $this->_locale->getWeekDayName($day,'abbreviated',true);
  339             case 'cccc':
  340                 return $this->_locale->getWeekDayName($day,'wide',true);
  341             case 'ccccc':
  342                 return $this->_locale->getWeekDayName($day,'narrow',true);
  343             default:
  344                 throw new CException(Yii::t('yii','The pattern for day of the week must be "E", "EE", "EEE", "EEEE", "EEEEE", "e", "ee", "eee", "eeee", "eeeee", "c", "cccc" or "ccccc".'));
  345         }
  346     }
  347 
  348     /**
  349      * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
  350      * @param string $pattern a pattern.
  351      * @param array $date result of {@link CTimestamp::getdate}.
  352      * @throws CException if "period" pattern is unknown
  353      * @return string AM or PM designator
  354      */
  355     protected function formatPeriod($pattern,$date)
  356     {
  357         if($pattern==='a')
  358         {
  359             if(intval($date['hours']/12))
  360                 return $this->_locale->getPMName();
  361             else
  362                 return $this->_locale->getAMName();
  363         }
  364         else
  365             throw new CException(Yii::t('yii','The pattern for AM/PM marker must be "a".'));
  366     }
  367 
  368     /**
  369      * Get the hours in 24 hour format, i.e. [0-23].
  370      * "H" for non-padding, "HH" will always return 2 characters.
  371      * @param string $pattern a pattern.
  372      * @param array $date result of {@link CTimestamp::getdate}.
  373      * @throws CException if "hour24" pattern is unknown
  374      * @return string hours in 24 hour format.
  375      */
  376     protected function formatHour24($pattern,$date)
  377     {
  378         $hour=$date['hours'];
  379         if($pattern==='H')
  380             return $hour;
  381         elseif($pattern==='HH')
  382             return str_pad($hour,2,'0',STR_PAD_LEFT);
  383         else
  384             throw new CException(Yii::t('yii','The pattern for 24 hour format must be "H" or "HH".'));
  385     }
  386 
  387     /**
  388      * Get the hours in 12 hour format, i.e., [1-12]
  389      * "h" for non-padding, "hh" will always return 2 characters.
  390      * @param string $pattern a pattern.
  391      * @param array $date result of {@link CTimestamp::getdate}.
  392      * @throws CException if "hour12" pattern is unknown
  393      * @return string hours in 12 hour format.
  394      */
  395     protected function formatHour12($pattern,$date)
  396     {
  397         $hour=$date['hours'];
  398         $hour=($hour==12|$hour==0)?12:($hour)%12;
  399         if($pattern==='h')
  400             return $hour;
  401         elseif($pattern==='hh')
  402             return str_pad($hour,2,'0',STR_PAD_LEFT);
  403         else
  404             throw new CException(Yii::t('yii','The pattern for 12 hour format must be "h" or "hh".'));
  405     }
  406 
  407     /**
  408      * Get the hours [1-24].
  409      * 'k' for non-padding, and 'kk' with 2 characters padding.
  410      * @param string $pattern a pattern.
  411      * @param array $date result of {@link CTimestamp::getdate}.
  412      * @throws CException if "hourInDay" pattern is unknown
  413      * @return integer hours [1-24]
  414      */
  415     protected function formatHourInDay($pattern,$date)
  416     {
  417         $hour=$date['hours']==0?24:$date['hours'];
  418         if($pattern==='k')
  419             return $hour;
  420         elseif($pattern==='kk')
  421             return str_pad($hour,2,'0',STR_PAD_LEFT);
  422         else
  423             throw new CException(Yii::t('yii','The pattern for hour in day must be "k" or "kk".'));
  424     }
  425 
  426     /**
  427      * Get the hours in AM/PM format, e.g [0-11]
  428      * "K" for non-padding, "KK" will always return 2 characters.
  429      * @param string $pattern a pattern.
  430      * @param array $date result of {@link CTimestamp::getdate}.
  431      * @throws CException if "hourInPeriod" pattern is unknown
  432      * @return integer hours in AM/PM format.
  433      */
  434     protected function formatHourInPeriod($pattern,$date)
  435     {
  436         $hour=$date['hours']%12;
  437         if($pattern==='K')
  438             return $hour;
  439         elseif($pattern==='KK')
  440             return str_pad($hour,2,'0',STR_PAD_LEFT);
  441         else
  442             throw new CException(Yii::t('yii','The pattern for hour in AM/PM must be "K" or "KK".'));
  443     }
  444 
  445     /**
  446      * Get the minutes.
  447      * "m" for non-padding, "mm" will always return 2 characters.
  448      * @param string $pattern a pattern.
  449      * @param array $date result of {@link CTimestamp::getdate}.
  450      * @throws CException if "minutes" pattern is unknown
  451      * @return string minutes.
  452      */
  453     protected function formatMinutes($pattern,$date)
  454     {
  455         $minutes=$date['minutes'];
  456         if($pattern==='m')
  457             return $minutes;
  458         elseif($pattern==='mm')
  459             return str_pad($minutes,2,'0',STR_PAD_LEFT);
  460         else
  461             throw new CException(Yii::t('yii','The pattern for minutes must be "m" or "mm".'));
  462     }
  463 
  464     /**
  465      * Get the seconds.
  466      * "s" for non-padding, "ss" will always return 2 characters.
  467      * @param string $pattern a pattern.
  468      * @param array $date result of {@link CTimestamp::getdate}.
  469      * @throws CException if "seconds" pattern is unknown
  470      * @return string seconds
  471      */
  472     protected function formatSeconds($pattern,$date)
  473     {
  474         $seconds=$date['seconds'];
  475         if($pattern==='s')
  476             return $seconds;
  477         elseif($pattern==='ss')
  478             return str_pad($seconds,2,'0',STR_PAD_LEFT);
  479         else
  480             throw new CException(Yii::t('yii','The pattern for seconds must be "s" or "ss".'));
  481     }
  482 
  483     /**
  484      * Get the week in the year.
  485      * @param string $pattern a pattern.
  486      * @param array $date result of {@link CTimestamp::getdate}.
  487      * @throws CException if "weekInYear" pattern is unknown
  488      * @return integer week in year
  489      */
  490     protected function formatWeekInYear($pattern,$date)
  491     {
  492         if($pattern==='w')
  493             return @date('W',@mktime(0,0,0,$date['mon'],$date['mday'],$date['year']));
  494         else
  495             throw new CException(Yii::t('yii','The pattern for week in year must be "w".'));
  496     }
  497 
  498     /**
  499      * Get week in the month.
  500      * @param array $pattern result of {@link CTimestamp::getdate}.
  501      * @param string $date a pattern.
  502      * @throws CException if "weekInMonth" pattern is unknown
  503      * @return integer week in month
  504      */
  505     protected function formatWeekInMonth($pattern,$date)
  506     {
  507         if($pattern==='W')
  508         {
  509             $weekDay=date('N',mktime(0,0,0,$date['mon'],1,$date['year']));
  510             return floor(($weekDay+$date['mday']-2)/7)+1;
  511         }
  512         else
  513             throw new CException(Yii::t('yii','The pattern for week in month must be "W".'));
  514     }
  515 
  516     /**
  517      * Get the timezone of the server machine.
  518      * @param string $pattern a pattern.
  519      * @param array $date result of {@link CTimestamp::getdate}.
  520      * @throws CException if "timeZone" pattern is unknown
  521      * @return string time zone
  522      * @todo How to get the timezone for a different region?
  523      */
  524     protected function formatTimeZone($pattern,$date)
  525     {
  526         if($pattern[0]==='z' || $pattern[0]==='v')
  527             return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
  528         elseif($pattern[0]==='Z')
  529             return @date('P', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
  530         else
  531             throw new CException(Yii::t('yii','The pattern for time zone must be "z" or "v".'));
  532     }
  533 
  534     /**
  535      * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
  536      * @param string $pattern a pattern.
  537      * @param array $date result of {@link CTimestamp::getdate}.
  538      * @throws CException if "era" pattern is unknown
  539      * @return string era
  540      * @todo How to support multiple Eras?, e.g. Japanese.
  541      */
  542     protected function formatEra($pattern,$date)
  543     {
  544         $era=$date['year']>0 ? 1 : 0;
  545         switch($pattern)
  546         {
  547             case 'G':
  548             case 'GG':
  549             case 'GGG':
  550                 return $this->_locale->getEraName($era,'abbreviated');
  551             case 'GGGG':
  552                 return $this->_locale->getEraName($era,'wide');
  553             case 'GGGGG':
  554                 return $this->_locale->getEraName($era,'narrow');
  555             default:
  556                 throw new CException(Yii::t('yii','The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".'));
  557         }
  558     }
  559 }