Unixタイムスタンプとは?
Unixタイムスタンプは単一の数値です。Unixエポック(1970年1月1日 00:00:00 UTCと定義)からの経過秒数をカウントしたものです。それだけです。タイムゾーンも、日付文字列も、月名もありません。1秒ごとに1ずつ増加する整数です。
エポックは固定され普遍的であるため、1700000000のようなタイムスタンプは地球上のどこでもまったく同じ瞬間を意味します。東京のサーバーとシカゴのノートパソコンは、どちらもこれが2023年11月14日 22:13:20 UTCを指すことに同意します。ローカルの表示はタイムゾーンによって異なりますが、基になる数値は決して変わりません。
意図的な単純化の一つ:Unix時間はうるう秒を無視します。1日は正確に86,400秒であると仮定します。これは天文学的な現実とは完全には一致しませんが、算術をクリーンに保ちます。詳細は後述します。
エンジニアが好む理由
タイムスタンプはソフトウェアの至る所に存在します。ファイルの変更時刻、データベースレコード、APIレスポンス、JWTの有効期限フィールド、ログ行などです。その理由は次の通りです。
- 単一の値であること。 1つの整数で完全な日時を格納します。パースの必要も、
MM/DDとDD/MMの曖昧さもありません。 - タイムゾーンに依存しないこと。 数値は常にUTCです。人間に表示するときだけローカル時間に変換します。
- 比較とソートが簡単であること。 どちらのイベントが先か?小さい方の整数です。2つのイベント間の期間?引き算するだけ。答えは秒単位です。
- コンパクトに格納できること。 フォーマットされた文字列ではなく、単一の4バイトまたは8バイトの整数です。
これが、インターフェースが親しみやすい2026-07-23を表示している場合でも、多くのインフラストラクチャが内部でエポック秒を使用している理由です。2つの表現間を移動したい場合は、Unixタイムスタンプ変換が双方向の変換を行います。
読み方:実例
タイムスタンプ1000000000を例に取ります。これは有名なもので、Unix愛好家の間で生放送中に桁上がりしました。
手動で読むには、秒をより大きな単位に分割します。おおよそ、1,000,000,000秒は約31.7年(1年は約31,556,952秒)です。これを1970年のエポックに加算すると、2001年に到達します。正確な瞬間は、2001年9月9日 01:46:40 UTCです。
この計算を手動で行うことはほとんどありません。すべての言語に組み込み関数があります。Pythonの場合:
```python from datetime import datetime, timezone datetime.fromtimestamp(1000000000, tz=timezone.utc)
2001-09-09 01:46:40+00:00
```
重要な点:変換は常にUTCに固定されています。この関数は、生の秒数をエポックから前方に進めることでカレンダー日付に変換します。代わりにローカル時間が必要な場合は、UTC変換の後にタイムゾーンオフセットを適用します。タイムスタンプ自体にはゾーン情報は含まれていません。
2038年問題
ここからが興味深いところです。そして、多くの一見しっかり構築されたシステムに内部で時限爆弾が仕掛けられている理由でもあります。
長年にわたり、Unix時間を保持するために使われてきたCの標準型time_tは、一般的に符号付き32ビット整数でした。符号付き32ビット整数は、−2,147,483,648から2,147,483,647までの値を表現できます。この上限が問題です。
1970年のエポックから秒をカウントすると、値2,147,483,647に達するのは2038年1月19日 03:14:07 UTCです。次の1秒後、カウンターは2,147,483,648になる必要があります。しかし、その数値は符号付き32ビット整数に収まりません。増加を続ける代わりに、ビットはオーバーフローしてラップアラウンドし、最も負の値である−2,147,483,648になります。
負のタイムスタンプは、エポックより前の時間として解釈されます。つまり、時計は止まるだけでなく、1901年12月13日に逆戻りします。32ビットのtime_tを信頼していたシステムは、突然、自分が20世紀初頭にいると認識します。
これはしばしばY2K38バグまたはUnixミレニアムバグと呼ばれ、構造的には2000年問題を引き起こしたのと同じ固定幅オーバーフローです。ただし、より先の未来にあり、2桁の年ではなくバイナリ整数の限界に根ざしています。
実際に影響を受ける箇所
現代の64ビットデスクトップとサーバーは、何年も前にほぼ修正されました。リスクは、更新が難しい場所に集中しています。
- 組み込みシステムおよび産業用システム。 32ビットの
time_tで出荷され、20年以上そのまま稼働し続ける可能性のあるルーター、コントローラー、医療機器、自動車用ECU、IoTハードウェア。現在展開されている多くのデバイスは、2038年になってもまだ使用されているでしょう。 - レガシーCコード。 古い
time_t定義に対してコンパイルされたアプリケーション。特に、その型がディスク上のフォーマットやネットワークプロトコルに浸透している場合。 - 古いデータベースとファイルシステム。 タイムスタンプを32ビットフィールドにパックしていたストレージフォーマット。一部の古いシステムは、将来の日付(20年の住宅ローンや2038年を超える証明書の有効期限など)を処理する際に、すでに症状を示しています。
障害モードは常に劇的なクラッシュとは限りません。時には、微妙な日付計算ミスです。期限切れのトークンが有効と読まれたり、ソート順が逆転したり、スケジュールされたジョブが1901年に起動したりします。
修正:64ビット時間
修正方法は原理的には簡単です。time_tを64ビットに拡張します。符号付き64ビット整数は、実用的な地平をはるかに超えて秒をカウントできます。オーバーフローポイントは約2920億年先にあり、太陽の予想寿命をはるかに超えています。
現在のほとんどのオペレーティングシステムは、すでにこの移行を行っています。64ビットLinuxは64ビットのtime_tを使用します。32ビットLinuxでさえ、近年カーネルとglibcで64ビット時間サポートを獲得しました。難しいのは修正自体ではなく、すべてのファームウェア、保存フォーマット、サードパーティバイナリを見つけて再構築することです。これらはまだ32ビットを前提としています。この監査作業こそが、本当の2038年プロジェクトです。
うるう秒の扱い
天文時と原子時はわずかにずれるため、公式のUTCは時々うるう秒を挿入して、時計を地球の自転に合わせます。Unix時間は、設計上、これらが存在しないふりをします。1日を86,400秒とハードコードします。
うるう秒が発生すると、システムは通常、それを「スミア」します。つまり、余分な秒をある時間枠(Googleは24時間のスミアを普及させました)に分散させ、時計が不可能な23:59:60を表示する必要がないようにします。結果として、Unixタイムスタンプはスムーズで単調増加を維持しますが、スミア中は厳密なUTCからごくわずかにずれるという代償を払います。事実上すべてのソフトウェアにとって、これはまさに望ましいトレードオフです。2038年のオーバーフローは整数幅の問題です。うるう秒は別の、はるかに小さな定義の癖です。混同しないでください。
重要なポイント
- Unixタイムスタンプは、1970年1月1日 00:00:00 UTCからの秒数であり、うるう秒は無視されます。
- 単一のタイムゾーンに依存しない整数であり、保存、比較、ソートが簡単です。
- 変換は常にUTCを基準とし、ローカル時間は後で適用されます。
- 符号付き32ビットの
time_tは、2038年1月19日 03:14:07 UTCでオーバーフローし、負の値にラップして1901年にジャンプします。 - 修正方法は64ビットの
time_tです。課題は、組み込みシステムとレガシーシステムを監査することです。
実際の動作を確認したいですか?任意のエポック値をUnixタイムスタンプ変換に貼り付けて、人間が読める日付として読み取るか、逆に日付をタイムスタンプに変換してください。
よくある質問
Unixタイムスタンプは秒単位ですか、それともミリ秒単位ですか?
古典的なUnix時間は秒単位です。ただし、JavaScriptや多くのWeb APIはエポックからのミリ秒を使用するため、1700000000000のような値は1,000倍大きくなります。簡単な見分け方:最近の日付の秒ベースのタイムスタンプは10桁、ミリ秒ベースは13桁です。不明な場合は、変換する前に桁数を確認してください。
2038年問題で私のスマートフォンやノートパソコンはクラッシュしますか?
ほぼ間違いなくしません。現代の64ビットオペレーティングシステムはすでに64ビットのtime_tを使用しており、オーバーフローは数十億年先に押しやられています。本当のリスクは、長期間使用される組み込みデバイスと、依然として32ビット時間に依存しており、2038年までに更新されない可能性のある古いソフトウェアにあります。
Unixタイムスタンプは負の値になりますか?
はい。負の値は1970年のエポックより前の瞬間を表します。例えば、-1は1969年12月31日 23:59:59 UTCです。これはまさに2038年に32ビットオーバーフローが生成する値であり、時計が1901年に逆戻りして見える理由です。
Unix時間はなぜうるう秒を無視するのですか?
計算をシンプルで予測可能に保つためです。すべての日を正確に86,400秒として扱うことで、期間は単なる引き算になり、タイムスタンプは単調増加を維持します。天文UTCとのわずかな不一致は、うるう秒を「スミア」することで処理されます。これは、23:59:60というエッジケースに対処するよりも、ほぼすべてのアプリケーションが好む方法です。
コードを書かずにタイムスタンプを変換するにはどうすればよいですか?
オンラインツールを使用します。Unixタイムスタンプ変換はエポック値を受け取り、対応するUTCとローカルの日時を即座に表示し、カレンダー日付をタイムスタンプに戻す変換も行います。