← 全部文章

紀元時間詳解:Unix 時間戳零是什麼?

Unix 時間戳 0 是 1970 年 1 月 1 日 00:00:00 UTC。了解為什麼那個日期成為 Unix 紀元、負時間戳代表什麼、紀元的秒/毫秒/微秒有何不同,以及現代系統適用哪些限制。

Unix 時間戳 0 代表什麼

每個 Unix 時間戳都計數自單一參考點——1970 年 1 月 1 日 00:00:00 UTC——以來經過的時間。在 Unix 的原始定義中單位是秒,所以時間戳 0 正好是 1970 年 1 月 1 日的 UTC 午夜,86400 正好是 24 小時之後。現代系統也使用毫秒、微秒與奈秒,但參考點相同。每個正值表示紀元之後的某個瞬間;每個負值表示之前的瞬間。

為什麼是 1970 年 1 月 1 日?

這個日期由貝爾實驗室的 Unix 開發者在 1970 年代初選定,作為略早於 Unix 本身誕生的實用參考點。它需要足夠早,使一般系統時間戳為正;足夠近,以適配早期電腦的小整數範圍;又足夠簡單,便於心算核對。當 Unix 變得有影響力後,語言、作業系統、資料庫、日誌格式與網路協定都繼承了同一個起點。

  • Unix 自 1969 年起在貝爾實驗室開發 —— 紀元設在其稍前
  • 選擇 1 月 1 日作為乾淨的日曆邊界
  • 用 1970 年而非 1969 年,因為實作使用從零開始的計數器
  • 現代所有作業系統、語言與協定都繼承了這個紀元 —— 沒有競爭標準

負時間戳:1970 年之前的日期

負的 Unix 時間戳表示 1970 年 1 月 1 日 00:00:00 UTC 之前的瞬間。大多數現代 64 位系統都能正確支援,這對歷史資料、出生日期、封存記錄,以及與紀元早於 Unix 的系統互通很有用。較舊的函式庫與資料庫可能拒絕負值,因此歷史資料集值得做一次顯式的相容性檢查。

  • -1 = December 31, 1969 23:59:59 UTC (one second before the epoch)
  • -86400 = December 31, 1969 00:00:00 UTC (one day before the epoch)
  • -2208988800 = January 1, 1900 00:00:00 UTC
  • JavaScript: new Date(-86400 * 1000).toISOString() → '1969-12-31T00:00:00.000Z'

格式的實際上限

Unix 紀元本身不是上限;儲存型別才是。儲存在 32 位有號整數中的時間戳,會比儲存在 64 位整數、JavaScript 數字或資料庫原生 timestamp 型別中的時間戳早得多地失效。評估時間戳安全性時,既要問使用什麼單位,也要問用什麼數值型別儲存。

  • 32-bit signed integer max: 2,147,483,647 = January 19, 2038 03:14:07 UTC (the Year 2038 problem)
  • JavaScript Date max: 8,640,000,000,000,000 ms = September 13, 275760 CE
  • 64-bit signed integer max: ~9.2 × 10^18 seconds = year ~292 billion
  • PostgreSQL TIMESTAMPTZ max: January 1, 294276 CE

其他系統的紀元

Unix 並不是運算中使用的唯一紀元。其他系統出於歷史或技術原因定義了自己的參考點。

  • GPS 紀元:1980 年 1 月 6 日 00:00:00 UTC —— 由 GPS 衛星與接收機使用
  • Windows FILETIME:1601 年 1 月 1 日 00:00:00 UTC —— 以 100 奈秒為間隔
  • Apple Cocoa / NSDate:2001 年 1 月 1 日 00:00:00 UTC
  • Excel / Lotus 1-2-3:1900 年 1 月 1 日 —— 為相容 Lotus 而刻意保留的閏年差一錯誤
  • FAT 檔案系統:1980 年 1 月 1 日 00:00:00 本地時間

紀元的秒、毫秒、微秒與奈秒

timestamp 這個詞並不總是表明單位。Unix 秒在作業系統與後端語言中常見。Unix 毫秒在 JavaScript 與瀏覽器 API 中常見。微秒與奈秒出現在資料庫、追蹤系統與高解析度日誌中。單位同時決定精度與你看到的位數。

  • Seconds: 1700000000 — common in Python, PHP, Go, Ruby, C, and Unix command-line tools
  • Milliseconds: 1700000000000 — common in JavaScript Date and many web analytics systems
  • Microseconds: 1700000000000000 — common in some databases and event pipelines
  • Nanoseconds: 1700000000000000000 — common in high-resolution tracing and systems languages
  • Always document the unit when storing epoch values in APIs, CSV files, and database columns

紀元時間 vs UTC vs 本地時間

紀元時間是一個計數。UTC 是定義參考時刻的全球時間標準。本地時間是基於 America/New_York 或 Asia/Tokyo 這類時區的顯示選擇。Unix 時間戳不會因使用者出行而改變;改變的只是格式化的日曆日期與時間。

  • 同一個時間戳在不同時區可能顯示為不同的本地日期
  • UTC 輸出最適合日誌、API 與跨伺服器偵錯
  • 本地輸出最適合日曆、使用者介面與報表
  • 時區偏移在格式化時套用,並不儲存在 Unix 時間戳內部

紀元時間常見問題

The Unix epoch (1970-01-01 UTC) was inherited from Multics, the OS that influenced early Unix design. POSIX later standardized the time_t type with explicit semantics that differ from how the original Unix specs described it — and most other platforms count from a different epoch entirely.

  • Multics (1969) counted seconds from 1970-01-01 GMT; Unix adopted the same epoch in 1971
  • POSIX time_t is defined as a count of seconds since 1970 UTC, explicitly excluding leap seconds (every day is 86,400 ticks)
  • POSIX vs Unix terminology: in practice the two are used interchangeably; POSIX is the standardized name
  • Other software epochs differ widely:
  • Windows FILETIME — 1601-01-01 UTC (Gregorian-cycle start), 100-nanosecond intervals
  • .NET DateTime.Ticks — 0001-01-01, 100-nanosecond intervals
  • Apple / Core Data — 2001-01-01 UTC (Cocoa reference date), seconds
  • NTP — 1900-01-01 UTC, seconds; GPS — 1980-01-06, seconds (no leap seconds)
  • Julian Day — noon UT, 4713 BC (proleptic Julian), days
  • When importing time data, confirm the epoch before trusting the value as Unix time

Related articles

FAQ

Is epoch time always in seconds?
The classic Unix timestamp is seconds since 1970-01-01 00:00:00 UTC, but many systems use milliseconds, microseconds, or nanoseconds with the same epoch.
Can Unix timestamps represent dates before 1970?
Yes. Negative timestamps represent dates before the Unix epoch, though older libraries and databases may not support them.
Does a Unix timestamp include a timezone?
No. A Unix timestamp represents one instant in UTC. Timezone information is used only when converting that instant into a readable local date.
What is the maximum Unix timestamp?
It depends on the storage type, not the epoch. A 32-bit signed integer maxes out at 2,147,483,647 (January 19, 2038), while a 64-bit integer or a JavaScript number reaches hundreds of millions of years. See the Year 2038 problem for the details.