PHP轉換超過2023年的日期出錯問題解決

2021-09-17 01:39:26 字數 1873 閱讀 3976

最近在寫乙個專案介面。測試中發現伺服器上測試正常的功能,在本地一直有問題。一步步的排查,最終鎖定問題是由於函式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漏洞,也被稱為unix millennium bug

此漏洞將會影響到所有 32 位系統下用unix時間戳整數來記錄時間的php,及其它程式語言。乙個整型的變數所能儲存的最大時間為2038 年01月19 日 03:14:07。超過這個時間後,整型數值將會溢位。

64位系統下可以儲存的日期最遠日期是現在宇宙年齡的21倍——292億年。所以不會受到該漏洞影響。

如何知道你的系統是否收到該漏洞的影響。很簡單,直接使用strtotime去轉換乙個大於2023年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 日期轉換

php 抓昨天日期的 date d m y time 24 3600 其它一些日期 code 的應用.mysql日期和時間函式不求人 所有 mysql 日期函式 應該全都用到了吧.xd php 入門必讀 日期及時間 echo date y m d h i s n timestamp mktime d...

PHP 遇到 2023年的問題該如何解決

tsung s blog 2038年是很多系統都會遇到的問題 於 2038年1月19日3時14分07秒 會跳回 1970 或其他時間 詳細可見 2038年問題 php 在 2038 年的計算上,也都做好相關的處理囉 傳統 strtotime date 於 32bits 與 64bits 系統差異 d...

PHP 日期時間的轉換

使用 date create from format 函式 date create from format y m d h i s 2015 08 12 09 50 23 日期時間物件有個成員函式 format dt date create from format y m d h i s 2015 ...