关于PHP函数time() date() 和 strtotime() 的时区问题
最近项目中有个需求, 要记录新注册用户的次日登录情况, 于是写出了如下代码:
$create_time = '用户注册时间'; //格式 Y-m-d H:i:s
$time = time();
$lasttime = date('Y-m-d H:i:s', $time);
$current_day = floor($time / 86400);
$create_day = floor( strtotime($create_time) / 86400 );
$days = $current_day - $create_day;
switch ($days)
{
case 1:
$values['2day'] = 1; break; //次日登陆
case 6:
$values['7day'] = 1; break; //七日登陆
case 14:
$values['15day'] = 1; break; //十五日登陆
}
//执行SQL修改数据库相关字段
这段代码放到线上后, 出现了奇怪的BUG, 明明是当天注册的用户, 却出现了有次日登录的情况. 排查代码没有发现问题, 于是暂时搁置去忙其它事情. 然后在第6天时, 竟然又出现了有七日登陆的数据. 于是开始和同事正式解决这个问题, 最终发现是由于函数的时区原因导致, 具体如下:
time() 返回自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数.
上面是 time() 函数在手册中的说明, 重点是格林威治时间, time() 始终返回的是格林威治时间的时间戳. 当PHP设置过时区后, date() 在格式化时间的操作中会将 (当前时区的时间 - 格林威治时间) 的偏移量自动添加进去, 按东八区的时间算也就是8小时. strtotime() 同样会自动将时区的偏移量加入处理操作中. 所以这时上面代码中 strtotime($create_time) 得到的同样是格林威治时间. $current_day 与 $create_day 现在都是按照格林威治时间计算的天数, 而BUG也就出现在这里.
比如当前时间为 2015-02-02 07:00:00 那么格林威治时间为 2015-02-01 23:00:00 (当前时间减去8小时)
当前时间为 2015-02-02 09:00:00 格林威治时间为 2015-02-02 01:00:00
再通过 floor() 处理后, 就相当于格林威治时间的 2015-02-02 与 2015-02-01, 中间相差一天.
所以如果用户在7点多注册, 而在9点再次登录的情况下, $current_day - $create_day = 1.
测试代码如下:
//date_default_timezone_set('UTC'); //设置为格林威治时间
date_default_timezone_set('Asia/Shanghai'); //设置为东八区上海时间
$a = floor( strtotime('2015-02-02 07:00:00') / 86400 );
$b = floor( strtotime('2015-02-02 09:00:00') / 86400 );
echo $b - $a; // 结果 1
//将格林威治时间打开, 注释掉上海时间, 结果输出为 0.
最终解决BUG后的代码如下:
$create_time = '用户注册时间'; //格式 Y-m-d H:i:s
$time = time();
$lasttime = date('Y-m-d H:i:s', $time);
//时间戳总是获取的格林威治时间, strtotime()会自动添加当前时区的偏移量, 这里因时区问题导致天数计算出现一天的误差, 所以在处理时间戳时增加时区的偏移量
$current_day = floor( ($time + date('Z')) / 86400 );
$create_day = floor( (strtotime($create_time) + date('Z')) / 86400 );
$days = $current_day - $create_day;
switch ($days)
{
case 1:
$values['2day'] = 1; break; //次日登陆
case 6:
$values['7day'] = 1; break; //七日登陆
case 14:
$values['15day'] = 1; break; //十五日登陆
}
//执行SQL修改数据库相关字段
关于PHP函数time() date() 和 strtotime() 的时区问题的更多相关文章
- php中的date和strtotime函数妙用
php中的两个常用的日期相关函数date和strtotime,相信大家一定不陌生.但我们平时使用都只是基本功能,什么时间戳变日期格式,日期格式变时间戳. 其实这两个函数还有更深的用法: 1.date函 ...
- php时间函数time(),date(),mktime()区别
php时间函数time(),date(),mktime()区别 浏览:1161 发布日期:2014/12/18 分类:系统代码 关键字: php时间函数 time() date()mktime() ...
- PHP 时间 date,strtotime ,time计算1970开始的第几天
首先,需要看你的php时区配置参数 方式1:更改php配置文件,然后从其fast-cgi或者php调用的地方: 方式2:date_default_timezone_set('PRC'); date函数 ...
- JavaScript 基础(七) 箭头函数 generator Date JSON
ES6 标准新增了一种新的函数: Arrow Function(箭头函数). x => x *x 上面的箭头相当于: function (x){ return x*x; } 箭头函数相当于匿名函 ...
- js中的函数,Date对象,Math对象和数组对象
函数就是完成某个功能的一组语句,js中的函数由关键字 function + 函数名 + 一组参数定义;函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可以使代码的组织结构更多清晰. ...
- 玩转PHP(二)--PHP强大的时间函数:date()
PHP具有相对来说强大的时间函数date(),该方法有下列一系列参数: 例如: echo date("Y-m-d H:i:s"); //2015-01-09 13:03:30 如果 ...
- xe7 c++builder 日期时间头文件函数大全 date
c++builde r时间日期函数大全,在头文件System.DateUtils.hpp,不过没有IncMonth,因为这个函数定义在System.SysUtils.hpp里头了,唉 date,dat ...
- js匿名函数和date对象,math对象
匿名函数: <script type="text/javascript"> function (参数列表){ 要执行的语句块; } </script> 对象 ...
- 日期函数new Date()浏览器兼容性问题
项目上与时间相关的地方特别多,与时间格式相关都使用了moment.js轻量级日期处理库,在开发中出现了几次浏览器兼容性问题,所以总结一下new Date()和moment.js在各大浏览器中兼容性问题 ...
随机推荐
- The Same Game-POJ1027模拟
The Same Game Time Limit: 1000MS Memory Limit: 10000K Description The game named "Same" is ...
- 我的git与github学习历程
因为想要知道如何把代码放到github上,所以就百度了一下,然后找到一个<如何从github上面拷贝源码>的文章,就先进行练习了下 1.首先到git官网下载git版本控制工具的安装包, ...
- NOI 动态规划题集
noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...
- sendEmail报错:at /usr/share/perl5/vendor_perl/IO/Socket/SSL.pm
sendEmail发送邮件是出现以下报错: ******************************************************************* Using the ...
- CentOS系统启动流程
CentOS系统启动流程 POST --> Boot Sequence(BIOS) --> Boot Loader(MBR) --> kernel(ramdisk) --> r ...
- 常用open api
SNS类网站API Facebook - http://developers.facebook.com/ 人人网开放平台 - http://dev.renren.com/ 51.com开放平台 - h ...
- inline-boock的默认间距
1 2 3 4 div{width:900px;} div li{ display:inline-block; width:300px;} <ul> <li></ ...
- JavaScript的chapterI
JavaScript是一种由web浏览器进行解析和执行脚本语言,包括ECMAScript,DOM,BOM. JavaScript的最大作用是赋予页面动作,让页面动起来,已经动态的处理页面的数据. 应用 ...
- 【转载】DOS 系统和 Windows 系统有什么关系?为什么windows系统下可以执行dos命令?
作者:bombless 因为不同的系统都叫 Windows ,这些系统在界面上也有一定连续性并且因此可能造成误解,所以有必要稍微梳理一下几个不同的 Windows 系统.首先是 DOS 上的一个图形界 ...
- 微信小程序-画布组件
canvas 画布. 注: canvas 标签默认宽度300px.高度225px 同一页面中的 canvas-id 不可重复,如果使用一个已经出现过的 canvas-id,该 canvas 标签对应的 ...