1,php关于跨时区时间转换
服务器是新加坡的,平台访问客户主要来自美国,也有其他国家,lnmp环境设置了美国时区(America/New_York)。
需求是:根据客户端本地时区,转化本地显示时间。
/*
* 时区转换
*/
public static function getTimezone($time, $from, $to='Asia/Shanghai', $fm='Y-m-d H:i:s')
{
if(empty($fm)){
$fm='Y-m-d H:i:s';
}
if(empty($from)){
$from='America/New_York';
}
if($form==$to){
return date($fm, $time);
}
$tt = date("Y-m-d H:i:s",$time);
$ctime = '';
$userTimezone = new \DateTimeZone($from);
$gmtTimezone = new \DateTimeZone($to);
$myDateTime = new \DateTime($tt, $gmtTimezone);
$num = $userTimezone->getOffset($myDateTime)+14400+86400;
$ctime = date($fm, $myDateTime->format('U') + $num);
return $ctime;
}
2,相关时间转换问题
(1)如果要用到后台统计,查看者仅为国内人员,那么还需要转化为北京时间来进行统计显示.那么,就在该方法起始位置加入修改时区。
由于该统计用到了原生sql语句,因此还需要修改sql连接时区
date_default_timezone_set('PRC');
Yii::$app->db->createCommand("set time_zone = '+8:00'")->execute();//yii框架下,修改数据库连接时区
(2)根据功能模块写入北京时间日志
/**
* 初始化body参数,,\api\controllers\BaseController.php
*/
protected function initBody()
{
$request = Yii::$app->request;
................
//添加access日志
$this->addAccessFile($request);
.........
}
private function addAccessFile($request) {
$zone = date('O',time());//与格林威治时间相差的小时数,例如:+0200
$difftime = 800-(int)$zone;
$time = time() + $difftime*36;
$today = date('Ymd',$time);
$path = dirname(__DIR__).'/runtime/logs/access_'.$today.'/';
if (!is_dir($path)) {
$flag = mkdir($path,0777,true);
}
$module = str_replace('/','_',trim($request->url,'/'));
$filename = $module.'.log';
$content = date('Y-m-d H:i:s',$time).'--'.Tool::getIp().'--'.$request->url.'--'.json_encode($request->post())."\r\n";
file_put_contents($path.$filename,$content,FILE_APPEND);
}
(3)通过ip获取时区
/**
* 根据IP获取时区,默认为美国标准东部时区(-5)
* @return string
*/
public static function getTimezoneByIp($ip)
{
if(empty($ip)){
return '-5';
}
$key = '419cbd8ed9c8d32f7c6559b8322125188e37a851e13235ef0649fc3a493db912';//https://ipinfodb.com/register注册获取
$url = 'https://api.ipinfodb.com/v3/ip-city/?key='.$key.'&ip=' . $ip;
$res = self::httpGet($url);
if ($res['data']) {
$data = explode(';',$res['data']);
if($data[10]){
$zone = strstr($data[10],':',true);
return intval($zone);
}else{
return '-5';
}
}else{
return '-5';
}
}