Unixタイムスタンプ徹底解説:秒とミリ秒、タイムゾーン、2038年問題
1700000000 はいつなのか。なぜ13桁の数字を使うシステムがあるのか。なぜ時刻がちょうど9時間ずれるのか。いくつかの概念を押さえれば、時刻にまつわるバグの多くは消えます。
Unixタイムスタンプとは
Unixタイムスタンプ(Unix時間、エポック秒)は、1970年1月1日 00:00:00 UTC、つまりUnixエポックからの経過秒数を数えた1つの整数です。0 は 1970-01-01 00:00:00 UTC、1700000000 は 2023-11-14 22:13:20 UTC です。
ある瞬間を1つの数値で表すことには多くの利点があります。2つの瞬間の差は引き算1回で求められ、並べ替えや比較も簡単で、タイムゾーンや日付の書式に関係なく、同じ瞬間はどこでも同じ値になります。
0 → 1970-01-01 00:00:00 UTC
1700000000 → 2023-11-14 22:13:20 UTC
1735689600 → 2025-01-01 00:00:00 UTC
2147483647 → 2038-01-19 03:14:07 UTC
10桁か13桁か:秒かミリ秒か
現在の秒単位のタイムスタンプは10桁です。ところがJavaScriptの Date.now() やJavaの System.currentTimeMillis() はミリ秒、つまり13桁を返します。これを取り違えると、1970年1月21日や5万年後といった日付になってしまいます。
桁数を数えましょう。10桁なら秒、13桁ならミリ秒、16桁ならマイクロ秒です。APIのドキュメントに単位が書かれていなければ確認し、変換するときは1,000を掛けるか割ります。
タイムスタンプにタイムゾーンはない
最も重要なのは、タイムスタンプにはタイムゾーンがないという事実です。1700000000 は東京でもニューヨークでも同じ瞬間です。タイムゾーンが適用されるのは、数値を人が読める日付として表示するときだけです。同じ値がUTCでは22時13分、日本(UTC+9)では翌朝7時13分になります。
典型的な「9時間ずれる」バグは、この原則を破ることで起こります。UTCで保存したのに現地時刻のつもりで表示したり、オフセットのない現地時刻の文字列を保存してUTCとして読んだりするケースです。保存と送信はUTC(またはタイムスタンプ)で行い、表示は利用者のタイムゾーンで行いましょう。
夏時間の落とし穴
日本は現在夏時間を実施していませんが、米国や欧州の多くの国では春に時計を進め、秋に戻します。そのため「ニューヨークは東京より14時間遅い」は1年の一部の期間にしか当てはまらず、残りの期間の時差は13時間です。
-05:00 のような固定オフセットではなく、America/New_York のようなIANAのタイムゾーン名を使えば、切り替えが自動的に処理されます。海外のチームとの会議やジョブの設定をするときは、タイムゾーン計算ツールでその日付の実際のオフセットを確認しましょう。
2038年問題
符号付き32ビット整数で保存すると、タイムスタンプの最大値は 2,147,483,647、つまり2038年1月19日 03:14:07 UTC です。その1秒後に値がオーバーフローして負の数になり、1901年に戻ってしまいます。これが2038年問題です。
現在のOSや言語の多くは64ビットの時刻を使っていますが、古い組み込み機器、データベースのINT列、ファイル形式などには32ビットの値が残っています。長期有効な証明書や30年ローンのように遠い将来の日付を扱うシステムは今すぐ上限に達する可能性があるので、新しい設計では64ビット整数か適切な日付型を使いましょう。
うるう秒と精度
Unix時間は1日を常にちょうど86,400秒として扱い、うるう秒を無視します。そのため天文学的に正確な経過時間とはごくわずかにずれることがありますが、一般的なアプリケーションでは無視して問題ありません。国際度量衡総会は2035年までにうるう秒を廃止することを決定しています。
AIBIZAPのタイムスタンプ変換ツールに数値を貼り付けると、秒かミリ秒かを自動で判別し、UTCと選んだタイムゾーンの日付を表示します。各地の時刻の比較にはタイムゾーン計算ツールを、決まった時刻に繰り返すジョブにはcron生成ツールを使いましょう。