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

  • CDateTimeParser
  • CFileHelper
  • CFormatter
  • CLocalizedFormatter
  • CMarkdownParser
  • CPasswordHelper
  • CPropertyValue
  • CTimestamp
  • CVarDumper
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CDateTimeParser class file
  4:  *
  5:  * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
  6:  * @author Qiang Xue <qiang.xue@gmail.com>
  7:  * @author Tomasz Suchanek <tomasz[dot]suchanek[at]gmail[dot]com>
  8:  * @link http://www.yiiframework.com/
  9:  * @copyright 2008-2013 Yii Software LLC
 10:  * @license http://www.yiiframework.com/license/
 11:  */
 12: 
 13: /**
 14:  * CDateTimeParser converts a date/time string to a UNIX timestamp according to the specified pattern.
 15:  *
 16:  * The following pattern characters are recognized:
 17:  * <pre>
 18:  * Pattern |      Description
 19:  * ----------------------------------------------------
 20:  * d       | Day of month 1 to 31, no padding
 21:  * dd      | Day of month 01 to 31, zero leading
 22:  * M       | Month digit 1 to 12, no padding
 23:  * MM      | Month digit 01 to 12, zero leading
 24:  * MMM     | Abbreviation representation of month (available since 1.1.11; locale aware since 1.1.13)
 25:  * MMMM    | Full name representation (available since 1.1.13; locale aware)
 26:  * y       | 4 year digit, e.g., 2005 (available since 1.1.16)
 27:  * yy      | 2 year digit, e.g., 96, 05
 28:  * yyyy    | 4 year digit, e.g., 2005
 29:  * h       | Hour in 0 to 23, no padding
 30:  * hh      | Hour in 00 to 23, zero leading
 31:  * H       | Hour in 0 to 23, no padding
 32:  * HH      | Hour in 00 to 23, zero leading
 33:  * m       | Minutes in 0 to 59, no padding
 34:  * mm      | Minutes in 00 to 59, zero leading
 35:  * s       | Seconds in 0 to 59, no padding
 36:  * ss      | Seconds in 00 to 59, zero leading
 37:  * a       | AM or PM, case-insensitive (since version 1.1.5)
 38:  * ?       | matches any character (wildcard) (since version 1.1.11)
 39:  * ----------------------------------------------------
 40:  * </pre>
 41:  * All other characters must appear in the date string at the corresponding positions.
 42:  *
 43:  * For example, to parse a date string '21/10/2008', use the following:
 44:  * <pre>
 45:  * $timestamp=CDateTimeParser::parse('21/10/2008','dd/MM/yyyy');
 46:  * </pre>
 47:  *
 48:  * Locale specific patterns such as MMM and MMMM uses {@link CLocale} for retrieving needed information.
 49:  *
 50:  * To format a timestamp to a date string, please use {@link CDateFormatter}.
 51:  *
 52:  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 53:  * @author Qiang Xue <qiang.xue@gmail.com>
 54:  * @package system.utils
 55:  * @since 1.0
 56:  */
 57: class CDateTimeParser
 58: {
 59:     /**
 60:      * @var boolean whether 'mbstring' PHP extension available. This static property introduced for
 61:      * the better overall performance of the class functionality. Checking 'mbstring' availability
 62:      * through static property with predefined status value is much faster than direct calling
 63:      * of function_exists('...').
 64:      * Intended for internal use only.
 65:      * @since 1.1.13
 66:      */
 67:     private static $_mbstringAvailable;
 68: 
 69:     /**
 70:      * Converts a date string to a timestamp.
 71:      * @param string $value the date string to be parsed
 72:      * @param string $pattern the pattern that the date string is following
 73:      * @param array $defaults the default values for year, month, day, hour, minute and second.
 74:      * The default values will be used in case when the pattern doesn't specify the
 75:      * corresponding fields. For example, if the pattern is 'MM/dd/yyyy' and this
 76:      * parameter is array('minute'=>0, 'second'=>0), then the actual minute and second
 77:      * for the parsing result will take value 0, while the actual hour value will be
 78:      * the current hour obtained by date('H'). This parameter has been available since version 1.1.5.
 79:      * @return integer timestamp for the date string. False if parsing fails.
 80:      */
 81:     public static function parse($value,$pattern='MM/dd/yyyy',$defaults=array())
 82:     {
 83:         if(self::$_mbstringAvailable===null)
 84:             self::$_mbstringAvailable=extension_loaded('mbstring');
 85: 
 86:         $tokens=self::tokenize($pattern);
 87:         $i=0;
 88:         $n=self::$_mbstringAvailable ? mb_strlen($value,Yii::app()->charset) : strlen($value);
 89:         foreach($tokens as $token)
 90:         {
 91:             switch($token)
 92:             {
 93:                 case 'yyyy':
 94:                 case 'y':
 95:                 {
 96:                     if(($year=self::parseInteger($value,$i,4,4))===false)
 97:                         return false;
 98:                     $i+=4;
 99:                     break;
100:                 }
101:                 case 'yy':
102:                 {
103:                     if(($year=self::parseInteger($value,$i,1,2))===false)
104:                         return false;
105:                     $i+=strlen($year);
106:                     break;
107:                 }
108:                 case 'MMMM':
109:                 {
110:                     $monthName='';
111:                     if(($month=self::parseMonth($value,$i,'wide',$monthName))===false)
112:                         return false;
113:                     $i+=self::$_mbstringAvailable ? mb_strlen($monthName,Yii::app()->charset) : strlen($monthName);
114:                     break;
115:                 }
116:                 case 'MMM':
117:                 {
118:                     $monthName='';
119:                     if(($month=self::parseMonth($value,$i,'abbreviated',$monthName))===false)
120:                         return false;
121:                     $i+=self::$_mbstringAvailable ? mb_strlen($monthName,Yii::app()->charset) : strlen($monthName);
122:                     break;
123:                 }
124:                 case 'MM':
125:                 {
126:                     if(($month=self::parseInteger($value,$i,2,2))===false)
127:                         return false;
128:                     $i+=2;
129:                     break;
130:                 }
131:                 case 'M':
132:                 {
133:                     if(($month=self::parseInteger($value,$i,1,2))===false)
134:                         return false;
135:                     $i+=strlen($month);
136:                     break;
137:                 }
138:                 case 'dd':
139:                 {
140:                     if(($day=self::parseInteger($value,$i,2,2))===false)
141:                         return false;
142:                     $i+=2;
143:                     break;
144:                 }
145:                 case 'd':
146:                 {
147:                     if(($day=self::parseInteger($value,$i,1,2))===false)
148:                         return false;
149:                     $i+=strlen($day);
150:                     break;
151:                 }
152:                 case 'h':
153:                 case 'H':
154:                 {
155:                     if(($hour=self::parseInteger($value,$i,1,2))===false)
156:                         return false;
157:                     $i+=strlen($hour);
158:                     break;
159:                 }
160:                 case 'hh':
161:                 case 'HH':
162:                 {
163:                     if(($hour=self::parseInteger($value,$i,2,2))===false)
164:                         return false;
165:                     $i+=2;
166:                     break;
167:                 }
168:                 case 'm':
169:                 {
170:                     if(($minute=self::parseInteger($value,$i,1,2))===false)
171:                         return false;
172:                     $i+=strlen($minute);
173:                     break;
174:                 }
175:                 case 'mm':
176:                 {
177:                     if(($minute=self::parseInteger($value,$i,2,2))===false)
178:                         return false;
179:                     $i+=2;
180:                     break;
181:                 }
182:                 case 's':
183:                 {
184:                     if(($second=self::parseInteger($value,$i,1,2))===false)
185:                         return false;
186:                     $i+=strlen($second);
187:                     break;
188:                 }
189:                 case 'ss':
190:                 {
191:                     if(($second=self::parseInteger($value,$i,2,2))===false)
192:                         return false;
193:                     $i+=2;
194:                     break;
195:                 }
196:                 case 'a':
197:                 {
198:                     if(($ampm=self::parseAmPm($value,$i))===false)
199:                         return false;
200:                     if(isset($hour))
201:                     {
202:                         if($hour==12 && $ampm==='am')
203:                             $hour=0;
204:                         elseif($hour<12 && $ampm==='pm')
205:                             $hour+=12;
206:                     }
207:                     $i+=2;
208:                     break;
209:                 }
210:                 default:
211:                 {
212:                     $tn=self::$_mbstringAvailable ? mb_strlen($token,Yii::app()->charset) : strlen($token);
213:                     if($i>=$n || ($token{0}!='?' && (self::$_mbstringAvailable ? mb_substr($value,$i,$tn,Yii::app()->charset) : substr($value,$i,$tn))!==$token))
214:                         return false;
215:                     $i+=$tn;
216:                     break;
217:                 }
218:             }
219:         }
220:         if($i<$n)
221:             return false;
222: 
223:         if(!isset($year))
224:             $year=isset($defaults['year']) ? $defaults['year'] : date('Y');
225:         if(!isset($month))
226:             $month=isset($defaults['month']) ? $defaults['month'] : date('n');
227:         if(!isset($day))
228:             $day=isset($defaults['day']) ? $defaults['day'] : date('j');
229: 
230:         if(strlen($year)===2)
231:         {
232:             if($year>=70)
233:                 $year+=1900;
234:             else
235:                 $year+=2000;
236:         }
237:         $year=(int)$year;
238:         $month=(int)$month;
239:         $day=(int)$day;
240: 
241:         if(
242:             !isset($hour) && !isset($minute) && !isset($second)
243:             && !isset($defaults['hour']) && !isset($defaults['minute']) && !isset($defaults['second'])
244:         )
245:             $hour=$minute=$second=0;
246:         else
247:         {
248:             if(!isset($hour))
249:                 $hour=isset($defaults['hour']) ? $defaults['hour'] : date('H');
250:             if(!isset($minute))
251:                 $minute=isset($defaults['minute']) ? $defaults['minute'] : date('i');
252:             if(!isset($second))
253:                 $second=isset($defaults['second']) ? $defaults['second'] : date('s');
254:             $hour=(int)$hour;
255:             $minute=(int)$minute;
256:             $second=(int)$second;
257:         }
258: 
259:         if(CTimestamp::isValidDate($year,$month,$day) && CTimestamp::isValidTime($hour,$minute,$second))
260:             return CTimestamp::getTimestamp($hour,$minute,$second,$month,$day,$year);
261:         else
262:             return false;
263:     }
264: 
265:     /*
266:      * @param string $pattern the pattern that the date string is following
267:      */
268:     /* x2modstart */  
269:     // changed from private to public
270:     public static function tokenize($pattern)
271:     /* x2modend */ 
272:     {
273:         if(!($n=self::$_mbstringAvailable ? mb_strlen($pattern,Yii::app()->charset) : strlen($pattern)))
274:             return array();
275:         $tokens=array();
276:         $c0=self::$_mbstringAvailable ? mb_substr($pattern,0,1,Yii::app()->charset) : substr($pattern,0,1);
277: 
278:         for($start=0,$i=1;$i<$n;++$i)
279:         {
280:             $c=self::$_mbstringAvailable ? mb_substr($pattern,$i,1,Yii::app()->charset) : substr($pattern,$i,1);
281:             if($c!==$c0)
282:             {
283:                 $tokens[]=self::$_mbstringAvailable ? mb_substr($pattern,$start,$i-$start,Yii::app()->charset) : substr($pattern,$start,$i-$start);
284:                 $c0=$c;
285:                 $start=$i;
286:             }
287:         }
288:         $tokens[]=self::$_mbstringAvailable ? mb_substr($pattern,$start,$n-$start,Yii::app()->charset) : substr($pattern,$start,$n-$start);
289:         return $tokens;
290:     }
291: 
292:     /**
293:      * @param string $value the date string to be parsed
294:      * @param integer $offset starting offset
295:      * @param integer $minLength minimum length
296:      * @param integer $maxLength maximum length
297:      * @return string parsed integer value
298:      */
299:     protected static function parseInteger($value,$offset,$minLength,$maxLength)
300:     {
301:         for($len=$maxLength;$len>=$minLength;--$len)
302:         {
303:             $v=self::$_mbstringAvailable ? mb_substr($value,$offset,$len,Yii::app()->charset) : substr($value,$offset,$len);
304:             if(ctype_digit($v) && (self::$_mbstringAvailable ? mb_strlen($v,Yii::app()->charset) : strlen($v))>=$minLength)
305:                 return $v;
306:         }
307:         return false;
308:     }
309: 
310:     /**
311:      * @param string $value the date string to be parsed
312:      * @param integer $offset starting offset
313:      * @return string parsed day period value
314:      */
315:     protected static function parseAmPm($value, $offset)
316:     {
317:         $v=strtolower(self::$_mbstringAvailable ? mb_substr($value,$offset,2,Yii::app()->charset) : substr($value,$offset,2));
318:         return $v==='am' || $v==='pm' ? $v : false;
319:     }
320: 
321:     /**
322:      * @param string $value the date string to be parsed.
323:      * @param integer $offset starting offset.
324:      * @param string $width month name width. It can be 'wide', 'abbreviated' or 'narrow'.
325:      * @param string $monthName extracted month name. Passed by reference.
326:      * @return string parsed month name.
327:      * @since 1.1.13
328:      */
329:     protected static function parseMonth($value,$offset,$width,&$monthName)
330:     {
331:         $valueLength=self::$_mbstringAvailable ? mb_strlen($value,Yii::app()->charset) : strlen($value);
332:         for($len=1; $offset+$len<=$valueLength; $len++)
333:         {
334:             $monthName=self::$_mbstringAvailable ? mb_substr($value,$offset,$len,Yii::app()->charset) : substr($value,$offset,$len);
335:             if(!preg_match('/^[\p{L}\p{M}]+$/u',$monthName)) // unicode aware replacement for ctype_alpha($monthName)
336:             {
337:                 $monthName=self::$_mbstringAvailable ? mb_substr($monthName,0,-1,Yii::app()->charset) : substr($monthName,0,-1);
338:                 break;
339:             }
340:         }
341:         $monthName=self::$_mbstringAvailable ? mb_strtolower($monthName,Yii::app()->charset) : strtolower($monthName);
342: 
343:         $monthNames=Yii::app()->getLocale()->getMonthNames($width,false);
344:         foreach($monthNames as $k=>$v)
345:             $monthNames[$k]=rtrim(self::$_mbstringAvailable ? mb_strtolower($v,Yii::app()->charset) : strtolower($v),'.');
346: 
347:         $monthNamesStandAlone=Yii::app()->getLocale()->getMonthNames($width,true);
348:         foreach($monthNamesStandAlone as $k=>$v)
349:             $monthNamesStandAlone[$k]=rtrim(self::$_mbstringAvailable ? mb_strtolower($v,Yii::app()->charset) : strtolower($v),'.');
350: 
351:         if(($v=array_search($monthName,$monthNames))===false && ($v=array_search($monthName,$monthNamesStandAlone))===false)
352:             return false;
353:         return $v;
354:     }
355: }
356: 
API documentation generated by ApiGen 2.8.0