博主辛苦了,我要打赏银两给博主,犒劳犒劳站长。
【摘要】Y2K38 漏洞,又称 Unix Millennium Bug,此漏洞将会影响到所有 32 位系统下使用 UNIX 时间戳整数来记录时间的程序。而 PHP 7.0 之前的版本都是以 32 位(01111111 11111111 11111111 11111111)长度来保存时间的,即最大时间为 2038-01-19 03:14:07,超过这个时间,整数将会溢出。
今年是 2018 年,也就是说再过 20 年,就会出现 PHP 无法使用 strtotime 和 mktime 来解析正常的时间戳,本文讲讲两个解决办法。
首先,给出相关知识,时间纪元(Epoch Time 新纪元时间)是指从 1970-01-01 00:00:00 (北京时间 1970 年 01 月 01 日 08 时 00 分 00 秒)开始,时间戳每秒以 1 为整数计时,32 位系统能够表示的最大整数是:2147483647(21亿),相当于 68.1 年,而 1970 到 2038 就是这个数,最小整数为:-2147483648,负值则表示 1970 年之前的时间,最小年月时间为:1901 年 12 月 13 日 20 时 45 分 52 秒。
以下是一些相关信息,有助于加深对 Y2K38 的理解:
date_default_timezone_set("PRC");
$date = "1970-01-01 08:00:00"; // 东八区,从 08:00:00 起开始记录时间戳
echo strtotime($date); // 输出 0
echo "<br />";
$date = "1970-01-01 09:00:00"; // 东八区,从 08:00:00 起开始记录时间戳
echo strtotime($date); // 输出 3600
echo "<br />";
$date = "1970-01-01 07:00:00"; // 东八区,从 08:00:00 起开始记录时间戳
echo strtotime($date); // 输出 -3600
echo "<br />";
$date = "2048-01-01 07:00:00"; // 已超出最大记录数
var_dump(strtotime($date)); // 输出 boolean false
echo "<br />";
PHP 为了解决此问题,有如下二种方法:
方法(一) 在 php 5.2 以上版本,可以使用 DateTime 类
关于 DateTime 类的相关信息在 PHP 官网文档中有给出:
以下是小例子:
//datetime 转 unixtime
$dt = new DateTime('2050-12-31 12:00:00');
echo $dt->format('U'); // 输出:2556100800
echo '<br>';
//unixtime 转 datetime
$dt = new DateTime('@2556100800');
echo $dt->format('Y-m-d H:i:s'); // 输出:2050-12-31 12:00:00
方法(二)将 PHP 版本升级到 7.0 ,因为在 PHP 7.0 及以上的版本在 64 位系统上采用的是 64 位方式来记录时间戳的。
64 位系统则很难受到此问题的,64 位系统下可以保存的日期最远日期是现在宇宙年龄的 21 倍,即 292 亿年。
这所以就是为啥越来越多人推荐使用 64 位操作系统的原因,当然程序也应该是以操作系统的位数来计算时间的,因此这样无忧无虑的解决这个 Y2K38 问题。
版权归 马富天PHP博客 所有
本文标题:《PHP7.0 版本之前 strtotime 和 mktime 的 Y2K38 漏洞【最大时间为 2038 年】》
本文链接地址:http://www.mafutian.net/388.html
转载请务必注明出处,小生将不胜感激,谢谢! 喜欢本文或觉得本文对您有帮助,请分享给您的朋友 ^_^
顶0
踩0
评论审核未开启 |