最近项目中有个需求, 要记录新注册用户的次日登录情况, 于是写出了如下代码:

$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() 的时区问题的更多相关文章

  1. php中的date和strtotime函数妙用

    php中的两个常用的日期相关函数date和strtotime,相信大家一定不陌生.但我们平时使用都只是基本功能,什么时间戳变日期格式,日期格式变时间戳. 其实这两个函数还有更深的用法: 1.date函 ...

  2. php时间函数time(),date(),mktime()区别

    php时间函数time(),date(),mktime()区别   浏览:1161 发布日期:2014/12/18 分类:系统代码 关键字: php时间函数 time() date()mktime() ...

  3. PHP 时间 date,strtotime ,time计算1970开始的第几天

    首先,需要看你的php时区配置参数 方式1:更改php配置文件,然后从其fast-cgi或者php调用的地方: 方式2:date_default_timezone_set('PRC'); date函数 ...

  4. JavaScript 基础(七) 箭头函数 generator Date JSON

    ES6 标准新增了一种新的函数: Arrow Function(箭头函数). x => x *x 上面的箭头相当于: function (x){ return x*x; } 箭头函数相当于匿名函 ...

  5. js中的函数,Date对象,Math对象和数组对象

    函数就是完成某个功能的一组语句,js中的函数由关键字 function + 函数名 + 一组参数定义;函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可以使代码的组织结构更多清晰. ...

  6. 玩转PHP(二)--PHP强大的时间函数:date()

    PHP具有相对来说强大的时间函数date(),该方法有下列一系列参数: 例如: echo date("Y-m-d H:i:s"); //2015-01-09 13:03:30 如果 ...

  7. xe7 c++builder 日期时间头文件函数大全 date

    c++builde r时间日期函数大全,在头文件System.DateUtils.hpp,不过没有IncMonth,因为这个函数定义在System.SysUtils.hpp里头了,唉 date,dat ...

  8. js匿名函数和date对象,math对象

    匿名函数: <script type="text/javascript"> function (参数列表){ 要执行的语句块; } </script> 对象 ...

  9. 日期函数new Date()浏览器兼容性问题

    项目上与时间相关的地方特别多,与时间格式相关都使用了moment.js轻量级日期处理库,在开发中出现了几次浏览器兼容性问题,所以总结一下new Date()和moment.js在各大浏览器中兼容性问题 ...

随机推荐

  1. javaBean

    JavaBean是一个满足特定规范的java类, 1.该类必须是公共类 2.必须具有一个默认无参的public构造函数,从而可以使用new关键字直接对其进行实例化 3.实现可序列化接口 4.属性必须是 ...

  2. ThreadLocal是什么?保证线程安全

    早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 当使 ...

  3. Eclipse 的快捷键以及文档注释、多行注释的快捷键

    一.多行注释快捷键 1.选中你要加注释的区域,用ctrl+shift+C 或者ctrl+/ 会加上//注释2.先把你要注释的东西选中,用shit+ctrl+/ 会加上/*    */注释 3.以上快捷 ...

  4. asp.net-枚举绑定控件

    1.DropDownList asp.net页面: <asp:DropDownList ID="drpTemplateType" runat="server&quo ...

  5. 概率论与数理统计讲课PPT和往年期末试卷

    讲课PPT 第17课:数理统计的基本概念 注 : 我会陆续把讲课PPT放上去,大家可以下载. 往年试卷及解答 往年期末试卷及解答 注 : 供同学们参考以备考.

  6. Android first---xml文件生成与解析

    一.使用append进行xml生成 Message类属性:private String body;        private String date;       private String a ...

  7. 荒废了很久的java以及微信公众平台今天拿起来看了看:这里有很好的教程

    我的微信公众号刚刚起步: ,感兴趣可以关注一下. 关于java开发微信公众号有一个很好的教程博客:推荐一下:http://blog.csdn.net/lyq8479/article/details/8 ...

  8. LayoutControl让一个控件占据多行或者多列

    拖动一个layoutcontrol到form上之后,会自动附带一个layoutgroup 设置layoutgroup的layoutmode为table 设置layoutgroup的OptionsTab ...

  9. 关于ES3、ES5、ES6以及ES7所有数组的方法(api)的总结

    起因:工作用经常用到操作数组的方法,这里进行一下总结,我尽量以简洁的语言概括每个方法(api)的作用.如果您想快速定位,可以Control+F 然后搜相应的方法即可定位 :) ES3的数组方法 joi ...

  10. 微信https请求工具类

    工作中用到的微信https请求工具类. package com.gxgrh.wechat.tools; import com.gxgrh.wechat.wechatapi.service.System ...