Unix 時間戳轉換工具

您輸入的內容不會被儲存、記錄或分享。

將 Unix 時間戳轉換為易讀的日期,或反向轉換。單位會自動偵測,每個結果都會標示所屬時區。

使用方式

  1. 貼上時間戳,或如 2025-01-01T00:00:00 的日期。
  2. 如需其他時區,請自行選擇。
  3. 複製您需要的格式。

秒、毫秒,以及更小的單位

Unix 時間以秒為單位定義。JavaScript 的 Date 則以毫秒為單位。混用多種語言的程式碼中,幾乎每個日期錯誤都始於這條界線。

只要知道就能認出症狀。把秒數交給預期毫秒的程式,會落在 1970 年 1 月 1 日的凌晨;如果介面上某個日期顯示為 1970 年,幾乎可以肯定就是這個原因。把毫秒當成秒來讀,則會落在大約西元 55,000 年,這通常會被發現,但並非總是如此,因為有些顯示程式會照樣呈現而不報錯。

這裡的單位是依位數推斷的。這是一種經驗法則,但它可預測、也說得清楚:以現今的時間來說,秒是 10 位數、毫秒是 13 位數、微秒是 16 位數、奈秒是 19 位數,而且在任何實際會用到的日期範圍內都不會重疊。推斷出的單位會直接顯示,而不是默默套用,你也可以手動更改。微秒時間戳記常見於 Postgres 與 Chrome 追蹤檔;奈秒則見於 Go、Prometheus 與 InfluxDB。奈秒值超出 JavaScript 數字能精確表示的範圍,所以會用 BigInt 轉換。

時間戳記不包含什麼

Unix 時間戳記代表的是一個瞬間,僅此而已。它不帶時區、不帶偏移,也不帶曆法。在東京與里斯本讀同一個時間戳記的兩個人,看的是同一個瞬間,並會正確地寫下不同的當地時間。這是優點:瞬間毫無歧義,而當地時間永遠做不到這一點。

因此,時間戳記無法告訴你當地是哪一天,要轉成日期就必須選定時區。這裡的每個輸出都標明時區正是這個原因,而且一定會把 UTC 與你的當地時間並列顯示,方便直接比較。

這也代表時間戳記不適合儲存本質上屬於當地的東西。每週固定早上九點的會議、生日、店家的營業時間:這些都是綁定時區與規則的當地時間,存成瞬間的話,下次該時區的偏移改變時就會出錯。請儲存當地時間與時區名稱,需要時再計算出瞬間。

閏秒

Unix 時間的定義假設每天剛好是 86,400 秒。地球並不配合,所以 UTC 會插入閏秒來與地球自轉保持一致,自 1972 年以來共插入了 27 次。

由於定義中沒有閏秒的位置,Unix 時間處理閏秒的方式是重複一個值,而不是多加一秒。沒有任何 Unix 時間戳記代表閏秒本身,因此 Unix 時間與國際原子時(TAI)的差距並非固定,而是在數十年間逐漸擴大。任何用兩個 Unix 時間戳記相減來計算經過時間的程式,都會默默少算這段期間內的閏秒數;這幾乎從不重要,但偶爾非常重要。

大型雲端業者用「抹平」(smearing)來避免不連續:Google 與 AWS 把多出來的一秒分散到閏秒前後的一段時間裡,讓時鐘永遠不會重複同一個值,代價是那一天時鐘會走得稍微慢一點。要注意在這段期間,抹平過的時鐘與未抹平的時鐘並不一致;如果要跨供應商比較時間戳記,這點值得留意。

2038 年與其他界線

有號 32 位元整數會在 UTC 2038 年 1 月 19 日 03:14:07 用盡,下一秒就會繞回 1901 年 12 月。任何仍以 32 位元欄位儲存 Unix 時間的東西,例如嵌入式系統、舊檔案格式、從未擴充的資料庫欄位,都會在那時出錯。這也是本工具會標示超過該時間點之時間戳記的原因。64 位元儲存把上限推到遠超宇宙年齡,也是現今系統採用的做法。

無號 32 位元儲存則把界線移到 2106 年,代價是無法表示 1970 年以前的時間。負的時間戳記在這裡可以正常使用:-86400 是 1969 年 12 月 31 日,回溯到格里曆起始的日期也都能正確轉換。JavaScript 的 Date 也有自己的上限,是紀元前後各 8.64e15 毫秒,約 273,000 年;超出範圍的值會回報為超出範圍,而不是顯示成 Invalid Date。

文字格式,以及該輸出哪一種

ISO 8601 是書寫日期與時間的國際標準,而 RFC 3339 是網際網路協定所採用、規範更嚴格的子集。從 API 輸出時就用 RFC 3339 的寫法,也就是 2026-03-14T09:30:00Z,或是帶上像 +09:00 這種偏移量的形式。原因是它以文字排序時順序正確、語意毫不含糊,而且到哪裡都能解析。

結尾的 Z 表示 UTC,而像 +09:00 這樣的偏移量表示與 UTC 相差固定的量。兩者都不是時區。Asia/Tokyo 才是時區:它是一整套規則,說明任何一個日期上的偏移量是多少,並且包含歷來的變更紀錄。偏移量告訴你時鐘當時顯示什麼,只有時區名稱才能告訴你未來某個時刻它會顯示什麼。

資料中應該避免的格式包括:任何使用兩位數年份的寫法、任何以斜線分隔的寫法,以及來自郵件標頭的 RFC 2822 日期,後者還沿用了早已過時的時區縮寫。縮寫是其中最糟的一種:CST 同時是北美的 Central Standard Time、China Standard Time 和 Cuba Standard Time,而 IST 則同時涵蓋印度、愛爾蘭和以色列。

把時間存進資料庫

PostgreSQL 的 timestamptz 是多數應用程式真正需要的型別。儘管名稱如此,它並不儲存時區:寫入時把輸入轉成 UTC,讀取時再以連線階段所設定的時區呈現,而這正是表示一個瞬間時你想要的行為。單純的 timestamp 則原封不動存下你給的牆上時鐘文字,完全不帶時區,把兩個來源不同的這種值拿來比較,會安靜地產生毫無意義的結果。

MySQL 的 DATETIME 行為就像那個單純型別,而 TIMESTAMP 會轉成 UTC,但受限於在 2038 年結束的 32 位元範圍,對任何需要儲存未來日期的系統來說都是實實在在的限制。SQLite 根本沒有日期型別,你選擇哪種慣例它就存哪種,通常是 ISO 8601 文字或整數。

能跨過上述所有差異的紀律只有一條:以 UTC 儲存瞬間、在邊界處轉換,並在需要為使用者呈現或排程時,把使用者的時區存成獨立的欄位。如果某個值真的是當地的牆上時鐘時間,例如店家的營業時間或每天 09:00 的固定會議,就儲存當地時間加上時區名稱,等到需要時再計算出對應的瞬間,因為偏移量可能因為法規而改變。

時鐘彼此不一致,有些還會倒退

機器的牆上時鐘會由 NTP 調整,也就是說它可能往前跳,也可能往回撥。因此用兩個牆上時鐘讀數相減來量測時間長度,偶爾會得到負的經過時間,而且經常得到錯誤的數值。單調時鐘就是為此而存在:它只會往前走,performance.now、帶 CLOCK_MONOTONIC 的 clock_gettime,以及每一套效能測試函式庫用的都是它。

跨機器時問題更嚴重,因為兩台伺服器的時鐘從來不會完全同步。在分散式系統中依時間戳為事件排序,會得到與因果關係相矛盾的順序,例如回覆的記錄時間早於它所回應的訊息,這正是邏輯時鐘與序號存在的理由。

對一般應用程式而言,實用的建議要樸素得多:不要把時間戳當成唯一識別碼,不要假設時間戳相同的兩個事件就是同時發生,並且在比較不同機器上記錄的任何資料時,預期至少有數秒的時鐘偏差。權杖驗證之所以留有一段容許偏差,正是因為如此。

把時間呈現給人看

儲存下來的瞬間必須以讀者所在的時區、讀者所在地的格式、以及讀者的語言呈現。在 JavaScript 中,Intl.DateTimeFormat API 會依據瀏覽器設定一次處理好這三件事,而且它會照顧到人們手工處理時最常弄錯的細節:用正確語言顯示月份名稱、把日與月排成正確順序,並依當地慣例而非個人偏好決定採用 12 小時制還是 24 小時制。

相對時間,也就是「三小時前」「兩天後」這類寫法,對近期事件比較親切,對久遠的事件則反而更糟,因為沒有人能根據「431 天前」做出任何判斷。常見的做法是一兩天之內用相對時間,之後改用絕對日期,並讓使用者在滑鼠停留或長按時看到完整的時間戳。

有兩個細節會帶來看得見的差異。第一,用使用者的時區而非伺服器的時區來呈現日期,這意味著傳送一個瞬間並在用戶端格式化,而不是在伺服器端就先格式化成字串。第二,只要有可能造成混淆,就標上時區,因為沒有標註時區的會議時間,是讓人晚一小時到場最可靠的方式。

根本不存在的日期,以及其他邊界情況

在有日光節約時間的時區把工作排在 02:30,等於保證每年都會出一次事:這個時間在春季切換時並不存在,在秋季切換時則會出現兩次。必須剛好執行一次的工作,應該放在 UTC 下執行,或是排在一點到三點這個會發生切換的區間之外。

曆法運算另有自己的陷阱。1 月 31 日加一個月沒有唯一正確的答案,不同函式庫會給出 2 月 28 日或 3 月 3 日。跨越切換時,加 24 小時並不等於加一天。閏年需要完整的規則,也就是能被四整除,但整百年除外,而其中能被 400 整除的又要算回來;而 2 月 29 日每四年就會弄壞一次週年紀念日的邏輯。

邊界也是真實存在的。有號 32 位元時間在 2038 年 1 月 19 日結束,這對嵌入式裝置和舊的資料庫欄位仍然重要;JavaScript 的 Date 涵蓋 1970 年前後大約 273,000 年,超出範圍的值一律回報為無效。如果你的資料包含很遙遠的未來日期,例如房貸、退休金和典藏系統常有的情況,這兩者都值得測試。

常見問題

我的時間戳是秒還是毫秒?
看位數即可判斷。現今的時間戳若為秒是 10 位,毫秒 13 位,微秒 16 位,奈秒 19 位。本工具會自動偵測並告訴您採用了哪一種,因為混淆兩者是日期處理中最常見的錯誤:把秒當毫秒會落在 1970 年 1 月,把毫秒當秒則會落在數萬年後。
為什麼同一個時間戳顯示的時鐘時間不同?
Unix 時間戳是不帶時區的絕對時間點,對應的時鐘時間完全取決於所在地區。因此本工具的每個輸出都標示時區,並固定同時顯示 UTC。
2038 年會發生什麼事?
以有號 32 位元整數儲存 Unix 時間的系統會在 2038-01-19T03:14:07Z 溢位並繞回 1901 年。本工具會對超過該時點的時間戳提出警告。使用 64 位元儲存則不受影響。
Unix 時間包含閏秒嗎?
不包含。Unix 時間的定義假設每天恰好是 86,400 秒,因此閏秒會被略過而非計入。這也是它無法表示閏秒本身、且與 TAI 之間的換算並非單純位移的原因。
可以處理 1970 年之前的日期嗎?
可以。紀元之前的時間戳為負數,例如 -86400 代表 1969 年 12 月 31 日。

最後更新:

回報問題

請提供操作步驟、預期結果及實際結果。請移除機密與個人資料。

相關工具