Unixタイムスタンプとは|変換方法と、秒・ミリ秒を間違えないための判別法
APIのレスポンスやログに 1756166400 のような数値が入っていて、何時のことか分からない。Unixタイムスタンプです。仕組み自体は単純ですが、秒とミリ秒の取り違えとタイムゾーンの誤解が実務での事故につながります。
Unixタイムスタンプとは
1970年1月1日 00:00:00 UTC からの経過秒数を表す整数です。この起点を エポック(epoch) と呼びます。
0 → 1970-01-01 00:00:00 UTC
1000000000 → 2001-09-09 01:46:40 UTC
日時を単一の整数で表せるため、次の利点があります。
- 比較が単純:大小比較だけで前後関係が分かる
- 計算が容易:差を取れば経過秒数になる
- 形式のブレがない:
2026/08/26と26-08-2026のような表記揺れが起きない - 保存効率が良い:文字列より小さい
日時を文字列で持つと、フォーマットの解釈で必ず問題が起きます。システム間でやり取りする日時は、Unixタイムスタンプかタイムゾーン付きのISO 8601形式にするのが原則です。
落とし穴1:秒とミリ秒
最も多い事故がこれです。Unixタイムスタンプには「秒」と「ミリ秒」の2種類が流通しています。
| 単位 | 例 | 主な出どころ |
|---|---|---|
| 秒 | 1756166400(10桁) | UNIX系コマンド、PHP、多くのAPI |
| ミリ秒 | 1756166400000(13桁) | JavaScript、Java |
JavaScript の Date.now() はミリ秒を返します。一方、多くのAPIは秒を返します。この2つを混ぜると、1000倍ずれた日時になります。
new Date(1756166400) // → 1970年1月21日(1000倍小さい)
new Date(1756166400000) // → 2025年の正しい日時
判別方法
桁数で見分けられます。
| 桁数 | 単位 | 該当する年代 |
|---|---|---|
| 10桁 | 秒 | 2001年〜2286年 |
| 13桁 | ミリ秒 | 2001年〜2286年 |
当面、10桁なら秒、13桁ならミリ秒と判断して問題ありません。
Unixタイムスタンプ変換ツールは、この桁数から秒とミリ秒を自動判別します。どちらか分からない数値をそのまま貼り付けても、正しい日時に変換されます。変換結果には秒とミリ秒の両方の表記が併記されるため、どちらの形式で渡すべきか迷ったときの確認にも使えます。
見分けがつかないケース
1970年代前後の日時を扱う場合や、10桁のミリ秒値(1970年4月頃)を扱う場合は、桁数だけでは判別できません。データの出どころの仕様を確認するのが確実です。
判断に迷ったら、変換した結果が「現実的な日時か」を見てください。 1970年1月の日付が出たら、まず単位の取り違えを疑います。
落とし穴2:タイムゾーンを持たない
Unixタイムスタンプ自体にタイムゾーンの情報はありません。 常にUTC基準の経過秒数です。
タイムゾーンが関係するのは、人間が読む形式に変換するときだけです。
1756166400
→ UTC: 2025-08-26 00:00:00
→ JST: 2025-08-26 09:00:00 (+9時間)
同じ数値が、表示するタイムゾーンによって違う日時になります。 ここを理解していないと、次のような問題が起きます。
- ログの時刻がサーバーのタイムゾーン(UTC)で記録され、日本時間だと思って読んで9時間ずれる
- 「日付」で集計したとき、UTC基準とJST基準で境界が変わり、集計値が合わない
とくに2つ目は、日次バッチの集計で頻繁に起きる問題です。UTCの1日とJSTの1日は9時間ずれているため、「8月26日の売上」の定義がシステム間で食い違います。
変換ツールではUTCとJST(日本時間)を切り替えて確認できます。ログを読むときは、まずそのログがどちらの基準で記録されているかを確認してください。
なお、定期実行の設定でも同じ問題が起きます。cronもサーバーのタイムゾーンで動作するため、cron式の書き方もあわせて確認しておくと事故を防げます。
落とし穴3:2038年問題
Unixタイムスタンプを32ビット符号付き整数で保持しているシステムは、2038年1月19日 03:14:07 UTC を超えると値があふれます(オーバーフロー)。この時点で負の値になり、1901年として解釈されます。
現代の言語・データベースの多くは64ビットで扱うため、通常は問題になりません。ただし、次のケースでは注意が必要です。
- 古いC言語のコードで
time_tが32ビットの環境 - 組み込み機器
- 32ビット整数の型でタイムスタンプを保存しているデータベースのカラム
「将来の日時」を扱うシステム(契約満了日、有効期限など)では、2038年より先の日付が既に登場している可能性があります。遠い未来の話ではありません。
実務での使いどころ
ログの時刻を読む
サーバーログやアプリケーションログには、Unixタイムスタンプで時刻が記録されていることがあります。障害調査では、問題が起きた時刻の前後を絞り込むために変換が必要になります。
JSONログの場合は、JSON整形ツールで構造を整えてからタイムスタンプを抽出すると読みやすくなります。
有効期限の確認
JWT(JSON Web Token)の exp(有効期限)や iat(発行時刻)は、秒単位のUnixタイムスタンプです。「トークンが期限切れになっている」という不具合の調査では、この値を変換して現在時刻と比較します。
経過時間の計算
2つのタイムスタンプの差が、そのまま経過秒数になります。
終了 1756166400 - 開始 1756162800 = 3600秒(1時間)
日付をまたいでも、月をまたいでも、単純な引き算で正しい結果が得られます。これがUnixタイムスタンプの最大の利点です。 「2月28日の23時から3時間後」のような計算を、暦を考慮せずに行えます。
補足:閏秒はどう扱われるか
Unixタイムスタンプは、1日を常に86400秒として扱います。 実際には閏秒(うるうびょう)が挿入される日があり、その日は86401秒ありますが、Unixタイムスタンプはこれを表現しません。
そのため、厳密には「経過秒数」ではなく「閏秒を無視した経過秒数」です。通常の業務システムで問題になることはまずありませんが、ミリ秒単位の精度が要求される用途では意識する必要があります。
まとめ
- 1970年1月1日 UTC からの経過秒数
- 10桁は秒、13桁はミリ秒。 JavaScriptはミリ秒
- タイムスタンプ自体にタイムゾーンはない。 表示時に決まる
- UTCとJSTは9時間ずれる。日次集計の境界に注意
- 32ビット環境では2038年問題がある
- 差を取るだけで経過時間が出る。暦を考慮しなくてよいのが最大の利点
数値を見て「何時か分からない」状態で調査を進めると、時系列の判断を誤ります。変換ツールで一度確認してから作業を進めてください。