本篇主要分析下SuagrCRM中的日期时间处理。
./include/entryPoint.php
// 获取时间日期处理示例,并放入全局变量中
$timedate = TimeDate::getInstance();
$GLOBALS['timedate'] = $timedate;
./include/TimeDate.php
// 单例实现
public static function getInstance()
{
// 设置时区
if(empty(self::$timedate)) {
// 如果没有设置时区,那么判断到此后,都会在项目根目录写条日志
// 日志的配置在config.php里查看logger数组信息
if(ini_get('date.timezone') == '') {
// Remove warning about default timezone
date_default_timezone_set(@date('e'));
try {
$tz = self::guessTimezone();
} catch(Exception $e) {
$tz = "UTC"; // guess failed, switch to UTC
}
if(isset($GLOBALS['log'])) {
$GLOBALS['log']->fatal("Configuration variable date.timezone is not set, guessed timezone $tz. Please set date.timezone=\"$tz\" in php.ini!");
}
date_default_timezone_set($tz);
}
self::$timedate = new self;
}
return self::$timedate;
}
function guessTimezone($userOffset = 0) {
if (!is_numeric($userOffset)) {
return '';
}
$defaultZones = array(
'America/Anchorage', 'America/Los_Angeles', 'America/Phoenix', 'America/Chicago',
'America/New_York', 'America/Argentina/Buenos_Aires', 'America/Montevideo',
'Europe/London', 'Europe/Amsterdam', 'Europe/Athens', 'Europe/Moscow',
'Asia/Tbilisi', 'Asia/Omsk', 'Asia/Jakarta', 'Asia/Hong_Kong',
'Asia/Tokyo', 'Pacific/Guam', 'Australia/Sydney', 'Australia/Perth',
);
/*
object(DateTime)#1 (3) {
["date"]=>
string(19) "2016-01-13 15:17:45"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Asia/Shanghai"
}
*/
$now = new DateTime();
// 获取时区列表
$tzlist = timezone_identifiers_list();
if ($userOffset == 0) {
// 时差偏移量的秒数。UTC 西边的时区偏移量总是负的,UTC 东边的时区偏移量总是正的。 -43200 到 43200
$gmtOffset = date('Z');
// 时区标识(PHP 5.1.0 新加) 例如:UTC,GMT,Atlantic/Azores
$nowtz = date('e');
// 把本地所在的时区加入到$tzlist数组中
if (in_array($nowtz, $tzlist)) {
array_unshift($defaultZones, $nowtz);
} else {
// date('T') 本机所在的时区
// date('l') 星期几,完整的文本格式 Sunday 到 Saturday
// timezone_name_from_abbr 返回时区名称的缩写 Asia/Chongqing
$nowtz = timezone_name_from_abbr(date('T'), $gmtOffset, date('I'));
if (in_array($nowtz, $tzlist)) {
array_unshift($defaultZones, $nowtz);
}
}
} else {
$gmtOffset = $userOffset * 60;
}
// 下面两个循环是从小到大的范围查找时区
foreach ($defaultZones as $zoneName) {
$tz = new DateTimeZone($zoneName);
if ($tz->getOffset($now) == $gmtOffset) {
return $tz->getName();
}
}
// try all zones
foreach ($tzlist as $zoneName) {
$tz = new DateTimeZone($zoneName);
if ($tz->getOffset($now) == $gmtOffset) {
return $tz->getName();
}
}
return null;
}