关于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在各大浏览器中兼容性问题 ...
随机推荐
- C语言----------链表的简单操作
#include <stdio.h> #include <malloc.h> typedef struct node{ //定义节点类型 char data; //数据域 st ...
- Android系统中自定义按键的短按、双击、长按事件
在项目中碰到这样的问题: 由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成: 1.单击 ...
- Java SE 基础:注释
Java SE 基础:注释 一.注释定义 用于解释说明程序的文字. 二.注释的作用 1.解释说明程序,提高程序的可读性 2.可以帮助我们调试程序:通过注释代码块,检测错误位置 三.格式 1.单行注释 ...
- Android动态方式破解apk前奏篇(Eclipse动态调试smail源码)
一.前言 今天我们开始apk破解的另外一种方式:动态代码调试破解,之前其实已经在一篇文章中说到如何破解apk了: Android中使用静态方式破解Apk 主要采用的是静态方式,步骤也很简单,首先使用 ...
- java源代码跟踪
首先我们要学会的是将JDK源码加载Eclipse中. 1.点“窗口”——>"首选项",选择左边的"Java"——>"已安装的JRE&quo ...
- 公钥私钥和RSA算法
1, RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2, RSA算法原理(二) http: ...
- xml 方式更新和获取 配置文件 appSettings 节点 解决办法
最近在搞一个小程序,会用到动态修改配置文件来进行处理,在百度上找了很多办法,但是始终达不到我预想的效果,先列出程序运行环境和开发工具版本: 开发工具:VS2010 .Net 运行环境:4.0 有两种方 ...
- 关于Advertising Campaign
Advertise Campaigns 是指为了传播企业创意或者宣传主题而采取的一些列的整合营销(IMC)活动,也称为广告战役.广告战役主要在一段明确的时间内,通过不同的媒体渠道投放广告,现在经常会整 ...
- 不定长链表队列C语言实现
#ifndef _CONST_H_#define _CONST_H_ #include <stdio.h>#include <stdlib.h> typedef enum { ...
- my.cnf
skip-external-locking skip-name-resolve back_log= key_buffer_size=384M max_allowed_packet=4M thread_ ...