关于PHP转换超过2038年日期出错的问题解决


Posted in PHP onJune 28, 2017

前言

最近在写一个项目接口。测试中发现服务器上测试正常的功能,在本地一直有问题。一步步的排查,最终锁定问题是由于函数strtotime返回了一个false值,导致数据插入数据库失败。

相同代码运行结果不一样,原因那就是环境不一致导致。要么是PHP版本不同,要么是位数不同。

我电脑是64位的。这里是PHP位数不一致,服务器使用64位,而我本地是32位。而strtotime被传入了一个字符串2050-1-1 23:59:59,该参数大于了2038-1-19 03:14:07所以在32位PHP下直接返回false,而64位PHP不受影响。

Y2K38漏洞

导致上述问题的根本原因就是Y2K38漏洞,也被称为Unix Millennium Bug

32位系统或PHP

此漏洞将会影响到所有 32 位系统下用UNIX 时间戳整数来记录时间的 PHP,及其它编程语言。一个整型的变量所能保存的最大时间为 2038 年01月19 日 03:14:07。超过这个时间后,整型数值将会溢出。

64位系统或PHP

64位系统下可以保存的日期最远日期是现在宇宙年龄的21倍——292亿年。所以不会受到该漏洞影响。

如何检测

如何知道你的系统是否收到该漏洞的影响。很简单,直接使用strtotime去转换一个大于2038年1月19日03:14:07日期。或者使用date函数将一个大于2147454847时间戳转换为日期。

下面具体演示一下

方法一

echo date("Y-m-d H:i:s",2556115199);

上面结果如果返回2050-12-31 23:59:59那么就没有问题。如果返回1914-11-25 09:31:43那么就受收到影响。

方法二

var_dump(strtotime("2050-12-31 23:59:59"));

上面结果如果返回2556115199那么就正常。如果返回false那么也会受到影响。

解决方案

方案一

更换系统和PHP均为64位。这个代价比较大,但是可以永久解决问题。

方案二

PHP5.2版本之后提供了一个函数DateTime可以临时解决一下问题。

// 1、日期字符串转换为时间戳
$obj = new DateTime("2050-12-31 23:59:59");
echo $obj->format("U"); // 2556115199

// 2、时间戳转换为日期字符串
$obj = new DateTime("@2556115199"); // 这里时间戳前要写一个@符号
$timezone = timezone_open('Asia/HONG_KONG'); // 设置时区
$obj->setTimezone($timezone); 
echo $obj->format("Y-m-d H:i:s"); // 2050-12-31 23:59:59

// 而且DateTime还可以有其他玩法
$obj = new DateTime("2050-12-31 23:59:59");
echo $obj->format("Y/m/d H:i:s"); // 换种方式输入时间字符串2050/12/31 23:59:59

通过DateTime类来操作日期不会受到Y2K38漏洞的影响,可以最远支持到9999年12月31日

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP 和 MySQL 基础教程(四)
Oct 09 PHP
php上的memcache和memcached两个pecl库
Mar 29 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
Apr 25 PHP
基于PHP生成静态页的实现方法
May 10 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
Feb 18 PHP
Javascript与PHP验证用户输入URL地址是否正确
Oct 09 PHP
php中mysql操作buffer用法详解
Mar 19 PHP
php猴子选大王问题解决方法
May 12 PHP
PHP 匿名函数与注意事项详细介绍
Nov 26 PHP
PHP使用递归算法无限遍历数组示例
Jan 13 PHP
PHP学习笔记之session
May 06 PHP
详解laravel passport OAuth2.0的4种模式
Nov 04 PHP
YII2自动登录Cookie总是失效的解决方法
Jun 28 #PHP
php的常量和变量实例详解
Jun 27 #PHP
Zend Framework框架中实现Ajax的方法示例
Jun 27 #PHP
PHP用continue跳过本次循环中剩余代码的注意点
Jun 27 #PHP
PHP API接口必备之输出json格式数据示例代码
Jun 27 #PHP
利用PHP获取访客IP、地区位置、浏览器及来源页面等信息
Jun 27 #PHP
简单谈谈PHP面向对象之标识对象
Jun 27 #PHP
You might like
?繁体转换的class
2006/10/09 PHP
php下连接ftp实现文件的上传、下载、删除文件实例代码
2010/06/03 PHP
php中检查文件或目录是否存在的代码小结
2012/10/22 PHP
php判断终端是手机还是电脑访问网站的思路及代码
2013/04/24 PHP
ThinkPHP之M方法实例详解
2014/06/20 PHP
php实现的发送带附件邮件类实例
2014/09/22 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
利用PHP扩展Xhprof分析项目性能实践教程
2018/09/05 PHP
JavaScript中null与undefined分析
2009/07/25 Javascript
JavaScript模拟重力状态下抛物运动的方法
2015/03/03 Javascript
jQuery实现简单的DIV拖动效果
2016/02/19 Javascript
AngularJS入门教程之AngularJS 模板
2016/08/18 Javascript
完美解决js传递参数中加号和&号自动改变的方法
2016/10/11 Javascript
浅谈jQuery this和$(this)的区别及获取$(this)子元素对象的方法
2016/11/29 Javascript
jQuery实现给input绑定回车事件的方法
2017/02/09 Javascript
详解webpack 入门与解析
2018/04/09 Javascript
使用RN Animated做一个“添加购物车”动画的方法
2018/09/12 Javascript
JS动态显示倒计时效果
2019/12/12 Javascript
基于javascript实现移动端轮播图效果
2020/12/21 Javascript
python导入时小括号大作用
2017/01/10 Python
pandas apply 函数 实现多进程的示例讲解
2018/04/20 Python
python爬虫获取新浪新闻教学
2018/12/23 Python
解决pyinstaller打包pyqt5的问题
2019/01/08 Python
python实现批量命名照片
2020/06/18 Python
澳大利亚领先的孕妇服装品牌:Mamaway
2018/08/14 全球购物
怎样建立和理解非常复杂的声明?例如定义一个包含N 个指向返回 指向字符的指针的函数的指针的数组?
2013/03/19 面试题
高中的自我鉴定
2013/12/16 职场文书
农业资源与环境专业自荐信范文
2013/12/30 职场文书
秘书英文求职信
2014/04/16 职场文书
大学生通用个人自我评价
2014/04/27 职场文书
2015毕业寄语大全
2015/02/26 职场文书
毕业生的自我鉴定表范文
2019/05/16 职场文书
为什么mysql字段要使用NOT NULL
2021/05/13 MySQL
python numpy中multiply与*及matul 的区别说明
2021/05/26 Python
Mybatis是这样防止sql注入的
2021/12/06 Java/Android
Vue监视数据的原理详解
2022/02/24 Vue.js