| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <?php
- /**
- * Link : http://www.phpcorner.net
- * User : qingbing<780042175@qq.com>
- * Date : 2018-11-07
- * Version : 1.0
- */
- namespace Helper;
- defined('APP_CHARSET') or define('APP_CHARSET', 'utf-8');
- class DateTimeParser
- {
- /* @var bool 标志 php 的 "mbstring" 扩展是否为可用状态 */
- static private $_mbstringAvailable;
- /**
- * 将日期转化成时间戳
- * @param string $value
- * @param string $pattern
- * @param array $defaults 年,月,日,小时,分钟和秒的默认值
- * @return int|false 如果解析失败,则返回False
- */
- static public function parse($value, $pattern = 'MM/dd/yyyy', $defaults = [])
- {
- if (null === self::$_mbstringAvailable) {
- self::$_mbstringAvailable = extension_loaded('mbstring');
- }
- $ps = self::analysisPattern($pattern);
- $i = 0;
- $n = self::$_mbstringAvailable ? mb_strlen($value, APP_CHARSET) : strlen($value);
- foreach ($ps as $p) {
- switch ($p) {
- case 'yyyy':
- {
- if (false === ($year = self::parseInteger($value, $i, 4, 4)))
- return false;
- $i += 4;
- break;
- }
- case 'yy':
- {
- if (false === ($year = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($year);
- break;
- }
- case 'MM':
- {
- if (false === ($month = self::parseInteger($value, $i, 2, 2)))
- return false;
- $i += 2;
- break;
- }
- case 'M':
- {
- if (false === ($month = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($month);
- break;
- }
- case 'dd':
- {
- if (false === ($day = self::parseInteger($value, $i, 2, 2)))
- return false;
- $i += 2;
- break;
- }
- case 'd':
- {
- if (false === ($day = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($day);
- break;
- }
- case 'h':
- case 'H':
- {
- if (false === ($hour = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($hour);
- break;
- }
- case 'hh':
- case 'HH':
- {
- if (false === ($hour = self::parseInteger($value, $i, 2, 2)))
- return false;
- $i += 2;
- break;
- }
- case 'm':
- {
- if (false === ($minute = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($minute);
- break;
- }
- case 'mm':
- {
- if (false === ($minute = self::parseInteger($value, $i, 2, 2)))
- return false;
- $i += 2;
- break;
- }
- case 's':
- {
- if (false === ($second = self::parseInteger($value, $i, 1, 2)))
- return false;
- $i += strlen($second);
- break;
- }
- case 'ss':
- {
- if (false === ($second = self::parseInteger($value, $i, 2, 2)))
- return false;
- $i += 2;
- break;
- }
- case 'a':
- {
- if (false === ($ampm = self::parseAmPm($value, $i)))
- 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 = self::$_mbstringAvailable ? mb_strlen($p, APP_CHARSET) : strlen($p);
- if ($i >= $n || ($p{0} != '?' && (self::$_mbstringAvailable ? mb_substr($value, $i, $tn, APP_CHARSET) : substr($value, $i, $tn)) !== $p))
- 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) {
- $year = Unit::getFullYear($year);
- }
- $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 (Unit::isValidDate($year, $month, $day) && Unit::isValidTime($hour, $minute, $second)) {
- return Unit::getTimestamp($hour, $minute, $second, $month, $day, $year);
- }
- return false;
- }
- /**
- * 解析日期或时间的格式串
- * @param string $pattern
- * @return array
- */
- static protected function analysisPattern($pattern)
- {
- if (!($n = self::$_mbstringAvailable ? mb_strlen($pattern, APP_CHARSET) : strlen($pattern))) {
- return [];
- }
- $ps = [];
- $c0 = self::$_mbstringAvailable ? mb_substr($pattern, 0, 1, APP_CHARSET) : substr($pattern, 0, 1);
- for ($start = 0, $i = 1; $i < $n; ++$i) {
- $c = self::$_mbstringAvailable ? mb_substr($pattern, $i, 1, APP_CHARSET) : substr($pattern, $i, 1);
- if ($c !== $c0) {
- $ps[] = self::$_mbstringAvailable ? mb_substr($pattern, $start, $i - $start, APP_CHARSET) : substr($pattern, $start, $i - $start);
- $c0 = $c;
- $start = $i;
- }
- }
- $ps[] = self::$_mbstringAvailable ? mb_substr($pattern, $start, $n - $start, APP_CHARSET) : substr($pattern, $start, $n - $start);
- return $ps;
- }
- /**
- * 将相应的字符串转换成数字
- * @param string $value the date string to be parsed
- * @param int $offset starting offset
- * @param int $minLength minimum length
- * @param int $maxLength maximum length
- * @return string parsed integer value
- */
- static protected function parseInteger($value, $offset, $minLength, $maxLength)
- {
- for ($len = $maxLength; $len >= $minLength; --$len) {
- $v = self::$_mbstringAvailable ? mb_substr($value, $offset, $len, APP_CHARSET) : substr($value, $offset, $len);
- if (ctype_digit($v) && (self::$_mbstringAvailable ? mb_strlen($v, APP_CHARSET) : strlen($v)) >= $minLength) {
- return $v;
- }
- }
- return false;
- }
- /**
- * 解析上午"am"和下午"pm"
- * @param string $value the date string to be parsed
- * @param int $offset starting offset
- * @return string parsed day period value
- */
- static protected function parseAmPm($value, $offset)
- {
- $v = strtolower(self::$_mbstringAvailable ? mb_substr($value, $offset, 2, APP_CHARSET) : substr($value, $offset, 2));
- return $v === 'am' || $v === 'pm' ? $v : false;
- }
- }
|