32 位 PHP 時間戳問題

Yoger發表於2019-04-16

 今天遇到一個bug,strtotime('2099-12-12 00:00:00')的時候返回false。排查之後發現,是32位的unix時間戳漏洞,稱為Y2K38 漏洞。(64位PHP的不受此影響)

Y2K38 漏洞

Y2K38,又稱 Unix Millennium Bug,此漏洞將會影響到所有 32 位系統下用 UNIX 時間戳整數來記錄時間的 PHP,及其它程式語言。
一個整型的變數所能儲存的最大時間為 2038 年01月19 日 03:14:07。超過這個時間後,整型數值將會溢位。
從 1970 年 01 月 01 日開始,到世界標準時 2038 年 01 月 19 日星期二凌晨 03:14:07 超過 2^31 – 1。2^31 – 1 就是0x7FFFFFFF,相信很多程式設計員都看過,在 32 位系統裡,這表示最大的有符號整數。如果用它來表示秒數,大概相當於 68.1 年,從 1970 年到 2038 年剛好是這個數。


所有,當時間大於2038 年 01 月 19 日星期二凌晨 03:14:07時,整型數值將會溢位。
(可以透過使用DateTime解決這個問題)

  1. 輸出當前時間
    $datetime = new /DateTime();
    print_r($datetime->format('Y-m-d H:i:s'));
  2. 輸出Unix時間戳格式
    //(php版本大於5.2):
    $datetime = new /DateTime('2099-12-12 00:00:00');
    var_dump($datetime->format('U'));
  3. 根據給定的時間戳格式化為給定的時間
    $datetime = new /DateTime();
    $datetime->setTimestamp(4100688000);
    echo $datetime->format('Y-m-d H:i:s');
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章