关于 PHP 时间戳最大支持到 2038 年问题解决办法

warning: 这篇文章距离上次修改已过793天,其中的内容可能已经有所变动。

20191112215429.png20191112215429.png

原因分析

这个问题在 64 位的 PHP 版本中并不存在,因为是在 32 位版本中,以秒计算 PHP 只支持到 2147483648,即:2^31,到 2038-01-19 03:14:08。

有效的时间戳通常从 Fri, 13 Dec 1901 20:45:54 GMT 到 Tue, 19 Jan 2038 03:14:07 GMT(对应于 32 位有符号整数的最小值和最大值)。不是所有的平台都支持负的时间戳,那么日记范围就被限制为不能早于 Unix 纪元。这意味着在 1970 年 1 月 1 日之前的日期将不能用在 Windows,一些 Linux 版本,以及几个其它的操作系统中。不过 PHP 5.1.0 及更新的版本克服了此限制。 —— [ PHP手册 ]

解决办法

如果在32系统PHP 5.1.0之后的版本,可以使用new DateTime解决。代码如下:

将时间戳转为年月日:

$d = new DateTime("@21474836490");
$d->setTimezone(new DateTimeZone("PRC"));
echo $d->format("Y-m-d H:i:s");

将年月日转为时间戳:

$d = new DateTime('2650-07-06 16:21:30');
echo $d->format('U');

如果运行时,遇到如下报错:

WARNING: It is not safe to rely on the system’s timezone settings

建议在 php.ini 里加上找到 date.timezone 项,设置 date.timezone = "Asia/Shanghai",再重启环境。

利用 DateTime 的替代函数

传统 date 替代函数:

function newDate($curformat, $utc_value){
    while(1){
        if($utc_value > 2147483647){
            if(date('Y', $utc_value) < 2038){
                $mydate2 = new DateTime('@'.$utcValue);
                $string = $mydate2->format($curformat);
                break;
            }
        }
        $string = date($curformat, $utc_value);
        break;
    }
    return $string;
}

// 调用方法
$utc_value = 2247484647
$curformat = 'Y-m-d';
newDate($curformat, $utc_value);

传统 strtotime 替代函数:

function newStrToTime($str_time){
    $result = strtotime($str_time);
    if(empty($result)){
        $date = new DateTime($str_time);
        $result = $date->format('U');
    }
    return $result;
}

// 调用方法
$str_time = '2100-10-02';
newStrToTime($str_time);

具体 DateTime 类使用方法请详查 - [ PHP手册-DateTime类 ]

利用 DateTimeZone 的替代函数

1、Unix时间戳转日期

function unixtime_to_date($unixtime, $timezone = 'PRC') {
    $datetime = new DateTime("@$unixtime"); //DateTime类的bug,加入@可以将Unix时间戳作为参数传入
    $datetime->setTimezone(new DateTimeZone($timezone));
    return $datetime->format("Y-m-d H:i:s");
}

2、日期转Unix时间戳

function date_to_unixtime($date, $timezone = 'PRC') {
    $datetime= new DateTime($date, new DateTimeZone($timezone));
    return $datetime->format('U');
}

添加新评论