diff options
Diffstat (limited to 'framework/utils/CDateTimeParser.php')
| -rw-r--r-- | framework/utils/CDateTimeParser.php | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/framework/utils/CDateTimeParser.php b/framework/utils/CDateTimeParser.php new file mode 100644 index 0000000..2f09f93 --- /dev/null +++ b/framework/utils/CDateTimeParser.php @@ -0,0 +1,277 @@ +<?php +/** + * CDateTimeParser class file + * + * @author Wei Zhuo <weizhuo[at]gamil[dot]com> + * @author Qiang Xue <qiang.xue@gmail.com> + * @author Tomasz Suchanek <tomasz[dot]suchanek[at]gmail[dot]com> + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2011 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +/** + * CDateTimeParser converts a date/time string to a UNIX timestamp according to the specified pattern. + * + * The following pattern characters are recognized: + * <pre> + * Pattern | Description + * ---------------------------------------------------- + * d | Day of month 1 to 31, no padding + * dd | Day of month 01 to 31, zero leading + * M | Month digit 1 to 12, no padding + * MM | Month digit 01 to 12, zero leading + * yy | 2 year digit, e.g., 96, 05 + * yyyy | 4 year digit, e.g., 2005 + * h | Hour in 0 to 23, no padding + * hh | Hour in 00 to 23, zero leading + * H | Hour in 0 to 23, no padding + * HH | Hour in 00 to 23, zero leading + * m | Minutes in 0 to 59, no padding + * mm | Minutes in 00 to 59, zero leading + * s | Seconds in 0 to 59, no padding + * ss | Seconds in 00 to 59, zero leading + * a | AM or PM, case-insensitive (since version 1.1.5) + * ---------------------------------------------------- + * </pre> + * All other characters must appear in the date string at the corresponding positions. + * + * For example, to parse a date string '21/10/2008', use the following: + * <pre> + * $timestamp=CDateTimeParser::parse('21/10/2008','dd/MM/yyyy'); + * </pre> + * + * To format a timestamp to a date string, please use {@link CDateFormatter}. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @author Qiang Xue <qiang.xue@gmail.com> + * @version $Id: CDateTimeParser.php 2928 2011-02-01 17:41:51Z alexander.makarow $ + * @package system.utils + * @since 1.0 + */ +class CDateTimeParser +{ + /** + * Converts a date string to a timestamp. + * @param string $value the date string to be parsed + * @param string $pattern the pattern that the date string is following + * @param array $defaults the default values for year, month, day, hour, minute and second. + * The default values will be used in case when the pattern doesn't specify the + * corresponding fields. For example, if the pattern is 'MM/dd/yyyy' and this + * parameter is array('minute'=>0, 'second'=>0), then the actual minute and second + * for the parsing result will take value 0, while the actual hour value will be + * the current hour obtained by date('H'). This parameter has been available since version 1.1.5. + * @return integer timestamp for the date string. False if parsing fails. + */ + public static function parse($value,$pattern='MM/dd/yyyy',$defaults=array()) + { + $tokens=self::tokenize($pattern); + $i=0; + $n=strlen($value); + foreach($tokens as $token) + { + switch($token) + { + case 'yyyy': + { + if(($year=self::parseInteger($value,$i,4,4))===false) + return false; + $i+=4; + break; + } + case 'yy': + { + if(($year=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($year); + break; + } + case 'MM': + { + if(($month=self::parseInteger($value,$i,2,2))===false) + return false; + $i+=2; + break; + } + case 'M': + { + if(($month=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($month); + break; + } + case 'dd': + { + if(($day=self::parseInteger($value,$i,2,2))===false) + return false; + $i+=2; + break; + } + case 'd': + { + if(($day=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($day); + break; + } + case 'h': + case 'H': + { + if(($hour=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($hour); + break; + } + case 'hh': + case 'HH': + { + if(($hour=self::parseInteger($value,$i,2,2))===false) + return false; + $i+=2; + break; + } + case 'm': + { + if(($minute=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($minute); + break; + } + case 'mm': + { + if(($minute=self::parseInteger($value,$i,2,2))===false) + return false; + $i+=2; + break; + } + case 's': + { + if(($second=self::parseInteger($value,$i,1,2))===false) + return false; + $i+=strlen($second); + break; + } + case 'ss': + { + if(($second=self::parseInteger($value,$i,2,2))===false) + return false; + $i+=2; + break; + } + case 'a': + { + if(($ampm=self::parseAmPm($value,$i))===false) + return false; + if(isset($hour)) + { + if($hour==12 && $ampm==='am') + $hour=0; + else if($hour<12 && $ampm==='pm') + $hour+=12; + } + $i+=2; + break; + } + default: + { + $tn=strlen($token); + if($i>=$n || substr($value,$i,$tn)!==$token) + return false; + $i+=$tn; + break; + } + } + } + if($i<$n) + return false; + + if(!isset($year)) + $year=isset($defaults['year']) ? $defaults['year'] : date('Y'); + if(!isset($month)) + $month=isset($defaults['month']) ? $defaults['month'] : date('n'); + if(!isset($day)) + $day=isset($defaults['day']) ? $defaults['day'] : date('j'); + + if(strlen($year)===2) + { + if($year>=70) + $year+=1900; + else + $year+=2000; + } + $year=(int)$year; + $month=(int)$month; + $day=(int)$day; + + if( + !isset($hour) && !isset($minute) && !isset($second) + && !isset($defaults['hour']) && !isset($defaults['minute']) && !isset($defaults['second']) + ) + $hour=$minute=$second=0; + else + { + if(!isset($hour)) + $hour=isset($defaults['hour']) ? $defaults['hour'] : date('H'); + if(!isset($minute)) + $minute=isset($defaults['minute']) ? $defaults['minute'] : date('i'); + if(!isset($second)) + $second=isset($defaults['second']) ? $defaults['second'] : date('s'); + $hour=(int)$hour; + $minute=(int)$minute; + $second=(int)$second; + } + + if(CTimestamp::isValidDate($year,$month,$day) && CTimestamp::isValidTime($hour,$minute,$second)) + return CTimestamp::getTimestamp($hour,$minute,$second,$month,$day,$year); + else + return false; + } + + /* + * @param string $pattern the pattern that the date string is following + */ + private static function tokenize($pattern) + { + if(!($n=strlen($pattern))) + return array(); + $tokens=array(); + for($c0=$pattern[0],$start=0,$i=1;$i<$n;++$i) + { + if(($c=$pattern[$i])!==$c0) + { + $tokens[]=substr($pattern,$start,$i-$start); + $c0=$c; + $start=$i; + } + } + $tokens[]=substr($pattern,$start,$n-$start); + return $tokens; + } + + /* + * @param string $value the date string to be parsed + * @param integer $offset starting offset + * @param integer $minLength minimum length + * @param integer $maxLength maximum length + */ + protected static function parseInteger($value,$offset,$minLength,$maxLength) + { + for($len=$maxLength;$len>=$minLength;--$len) + { + $v=substr($value,$offset,$len); + if(ctype_digit($v) && strlen($v)>=$minLength) + return $v; + } + return false; + } + + /* + * @param string $value the date string to be parsed + * @param integer $offset starting offset + */ + protected static function parseAmPm($value, $offset) + { + $v=strtolower(substr($value,$offset,2)); + return $v==='am' || $v==='pm' ? $v : false; + } +} |
