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