Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • CChoiceFormat
  • CDateFormatter
  • CDbMessageSource
  • CGettextMessageSource
  • CLocale
  • CMessageSource
  • CMissingTranslationEvent
  • CNumberFormatter
  • CPhpMessageSource
  • Overview
  • Package
  • Class
  • Tree
  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: }
560: 
API documentation generated by ApiGen 2.8.0