古老問題了,即使影響十分廣泛也很嚴重,但是因為時間還久吧 !? 所以普遍被認為只要在 2038 年前修復即可,並沒有那麼有急迫性。

什麼是 Y2038 ?

Year 2038 problem,也被稱作 Y2038、Y2k38、Unix Y2K、Epochalypse、Friday 13th Bug,一種時間格式儲存上的臭蟲。

主要是因為以前在設計 timestamp 時使用 signed-32-bit (4-Bytes) 來儲存計算的秒數,而4 bytes能儲存表示的最大時間是 2038年1月19日3時14分07秒,在這個時間點之後的系統無法正常工作。即使用 unsigned-32-bit 儲存,例如比特幣的 timestamp, 也只能延後到 2106 年。

影響層面

作業系統

到 2038 年前,大概剩 Embedded systems 或 IoT 設備這類不會大幅更換。 其他桌機/雲設備/機房主機,按照現在的發展大概都會被汰換掉成 64 位元。

Binary file formats

從 wiki 上看起來至少使用 32位元 time_t 編碼的有 ZIP 檔案。

而像現在最流行的以 json-based 往上長的格式,就不會造成此問題,因為一定是用 string 傳遞, 如果會發生問題,也是會發生在 json parser 這一端,看你用什麼去接。

programming language

  • golang : go 沒有這個問題,因為 Time 本身就是用 64 bit 儲存

  • java : java 本身也是用 64-bit 來儲存時間,除非 developer 自己用 int 去接才會發生問題。

Database

  • mySQL、MariaDB : 欄位型態建議改用 DATETIME 不使用 TIMESTAMP。缺點就是要 APP 要理解 TimeZone。

  • postgreSQL : 至少在很多年前的 v10 版本,TIMESTAMP 型態就改成是 8 bytes 了,自然儲存上沒有這個問題。

Database query languages

  • SQL Query 不要使用內建的 UNIX_TIMESTAMP() 的 function
  • 以 MSSQL : 不使用 DATEDIFF(),回傳的也是 int,應改用 DATEDIFF_BIG() 回傳 bigint (8 bytes)

解決方案

不管問題發生在上述那一個層次,只要是使用 64 bit 儲存時間,就可以解決此問題。 反之,要檢查整個流程中,有沒有哪個環節被意外轉成 int(32-bit),會死在這裡。