Y2K 千禧蟲!?
相信年紀超過 30 以上的資深工程師們,多多少少都經歷過那段日子。
在過去那個記憶體和資料欄位「金金計較」的時代背景下,一堆年份以兩位數(00~99)做紀錄的資料,全都面臨 99 之後的下一年,就直接歸零的夢靨。
當時大家透過容量擴充和大量轉換的過程,在花了不少時間和經費(也爆掉好幾個新鮮的肝?)之後,好不容易地似乎完美地解決了這個世紀問題。
然而,就在最近。筆者因為手上專案,需要為某筆資料記錄,指定為一個特定的時間時,才發現….
咦!?
Why!!!!???
「設定2099-12-31」(一般人生的極限)…..
失敗!….
「設定 2050-12-31」(目前年輕人升級為老人的日子)…..
失敗!….
「設定 2045-12-31」(攻殼梗!!??…)….
失敗!….
「設定 2033-02-21」(某人六十大壽!!!!!?????…)
咦!!!??
成功了!!
WTF!!????
經歷上述研究並線上搜尋一些資訊後,才發現到…
原來,上次 Y2K 千禧蟲 事件後,其實還有另一隻同類,名為 Y2K38 的問題。
這組神秘數字是…. 「2038年01月19日 03:14:07」!
這次事件的關鍵,是所謂的 Unix 時間戳記(timestamp)造成的問題。
簡單來說,當初 Unix 時間戳記是以 32 位元有號整數(signed integer)的方式紀錄。
這樣的紀錄規格,數值可以表達 -2147483648 到 2147483647。
並且當數值為 0 時,基準時間代表「1970-01-01 00:00:00」(UTC+0)。
| 二進位 | 十進位 | 代表時間 |
| 1111 1111 1111 1111 1111 1111 1111 1111 | -2147483648 | 1901-12-13 20:45:52 |
| 0000 0000 0000 0000 0000 0000 0000 0000 | 0 | 1970-01-01 00:00:00 |
| 0111 1111 1111 1111 1111 1111 1111 1111 | 2147483647 | 2038-01-19 03:14:07 |
這表示,以這樣的形式規格,可以記錄(表達)1901-12-13 20:45:52 到 2038-01-19 03:14:07 之間的任何時間。
也就是目前絕大多數以 Unix timestamp 型式(32位元)紀錄的時間,所能表示(設定)的最大值:2038年1月19日3點14分07秒 。
這個問題,目前被定名為「Y2K38 problem」(2038問題)。
這問題就某方面來說,影響不大。因為之前 Y2K 問題,許多系統已經都有思考、規劃,並使用了可以處理更長遠日期和時間的實作方式。
但是,在另一方面,因為有很多系統還是習慣用著當初 2000 年不會出現的 Unix timestamp型式來做時間紀錄。
資訊界通常就是秉持著「沒有壞就不要修」的原則(?),很多地方就保留或習慣地繼續使用 Unix timestamp。等於間接地讓Y2K38 問題持續存在著。
當然相對於當初的 Y2K 千禧蟲, 這個 Y2K38 問題受影響的範圍相對較小,會有此問題的地方主要是在:
- 以秒為單位,只需要對資料做單純時間紀錄用的小型裝置
- 以 Unix timestamp 為基礎的系統 log 紀錄
- 以 timestamp 為資料型別的 資料庫 欄位
第一項,因為是單純資料收集記錄器,所以通常也不太需要去對小型裝置做什麼更動,而只要在那些原始資料最後收集或彙整的「資料彙整系統」上,在匯入時,多做一些轉換處理即可。
第二項,很多都是只要改一下紀錄時的時間格式設定,也可以輕鬆解決。
第三項 關於資料庫(database)部分,因為目前大多數的資料庫,資料型別為 timestamp 的,也多半都是使用 32 位元形式來處理。所以大致處理方向有二:
- 資料庫系統本身將 timestamp 型別的機制,整體升級至 64 位元。
- 改用同樣可以精確到秒數,且可以記錄到 9999-12-31 23:59:59 的 datetime 型別,來取代原本的 timestamp 型別。
還好,這個 Y2K38 問題應該是小很多。只是,如果在處理時間資料時,若沒注意到底層的時間機制用了 timestamp 所引發的這個小問題,很可能會花上半天,綠色乖乖也擺了好幾包,卻還是搞不定這個靈異事件的話,那就真的太冤了!~