关于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 相关文章推荐
文章推荐系统(三)
Oct 09 PHP
PHP脚本数据库功能详解(下)
Oct 09 PHP
追求程序速度,而不是编程的速度
Apr 23 PHP
PHP冒泡排序算法代码详细解读
Jul 17 PHP
PHP管理内存函数 memory_get_usage()使用介绍
Sep 23 PHP
深入理解PHP中的Session和Cookie
Jun 21 PHP
php操作mysqli(示例代码)
Oct 28 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
Jul 08 PHP
php的XML文件解释类应用实例
Sep 22 PHP
php通过rmdir删除目录的简单用法
Mar 18 PHP
Yii2实现UploadedFile上传文件示例
Feb 15 PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
Aug 30 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
Zend引擎的发展 [15]
2006/10/09 PHP
php 特殊字符处理函数
2008/09/05 PHP
使用GDB调试PHP代码,解决PHP代码死循环问题
2015/03/02 PHP
PHP实现即时输出、实时输出内容方法
2015/05/27 PHP
基于OpenCart 开发支付宝,财付通,微信支付参数错误问题
2015/10/01 PHP
Yii框架表单模型和验证用法
2016/05/20 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
javascript textarea光标定位方法(兼容IE和FF)
2011/03/12 Javascript
javascript将浮点数转换成整数的三个方法
2014/06/23 Javascript
javascript基于DOM实现权限选择实例分析
2015/05/14 Javascript
Javascript对象Clone实例分析
2015/06/09 Javascript
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
2015/08/21 NodeJs
SublimeText自带格式化代码功能之reindent
2015/12/27 Javascript
jQuery获得字体颜色16位码的方法
2016/02/20 Javascript
AngularJS 在同一个界面启动多个ng-app应用模块详解
2016/12/20 Javascript
从零学习node.js之简易的网络爬虫(四)
2017/02/22 Javascript
微信小程序媒体组件详解(视频,音乐,图片)
2017/09/19 Javascript
微信小程序实现图片放大预览功能
2020/10/22 Javascript
JavaScript实现的贝塞尔曲线算法简单示例
2018/01/30 Javascript
Vue核心概念Getter的使用方法
2019/01/18 Javascript
我所理解的JavaScript中的this指向
2020/09/04 Javascript
Python 开发Activex组件方法
2009/11/08 Python
python如何对实例属性进行类型检查
2018/03/20 Python
Python3安装psycopy2以及遇到问题解决方法
2019/07/03 Python
世界领先的电子书网站:eBooks.com(在线购买小说、非小说和教科书)
2019/03/30 全球购物
印度排名第一的蛋糕、鲜花和礼品送货:Winni
2019/08/02 全球购物
工程力学专业自荐信范文
2014/03/17 职场文书
家长会演讲稿
2014/04/26 职场文书
《鸟岛》教学反思
2014/04/26 职场文书
英语演讲稿3分钟
2014/04/29 职场文书
大学生助学金感谢信
2015/01/21 职场文书
社区义诊通知
2015/04/24 职场文书
仰望星空观后感
2015/06/10 职场文书
保护环境建议书作文400字
2015/09/14 职场文书
2016年“我们的节日·中秋节”活动总结
2016/04/05 职场文书
win10频率超出范围怎么办?win10老显示超出工作频率范围的解决方法
2022/07/07 数码科技