Unix タイムスタンプ変換
Unix タイムスタンプを任意のタイムゾーンの日時に、日時をエポック値に変換します。秒かミリ秒かは自動で判別し、ISO 8601 形式と、どれくらい前かも表示します。
Unix タイムスタンプとは何か
Unix タイムスタンプ — エポック時刻、あるいは POSIX 時刻とも呼ばれます — は、1970 年 1 月 1 日 00:00:00 UTC (Unix エポックと呼ばれる瞬間) から何秒が経過したかを数える単一の数値です。タイムゾーンも暦も書式もない一つの整数であるため、時間のある瞬間を保存・整列・比較したり、ネットワーク越しに送ったりする必要があるとき、コンピューターが手を伸ばす形式です。データベースの「created_at」列、JWT の「iat」「exp」クレーム、ファイルの mtime、そしてこれから読むほぼすべてのログファイルのタイムスタンプの背後にあるのがこれです。
引き換えになるのは、素の数値は人には何も意味しないことです。1716197600 は申し分なく正しい瞬間ですが、それが先週の火曜なのか 3 年前なのかはひと目では分かりません。その両方向の翻訳こそ、このツールが行うことです。
秒かミリ秒か — 人を噛む曖昧さ
元来の Unix の慣習は整数の秒を数え、シェルの date +%s、PHP の time()、切り捨てた Python の time.time() から得られるのがこれです。JavaScript、Java などの多くはミリ秒を数えます: Date.now() は 1000 倍大きな数を返します。どちらも「タイムスタンプ」と呼ばれ、取り違えることは最もよくある日付バグの一つです。
その失敗は大声ではなく静かに起きます。ミリ秒の値を秒として読めば日付は数万年先に飛び、秒の値をミリ秒として読めばすべてが 1970 年 1 月に潰れます。どちらもエラーを投げません — 本物に見える誤った日付が得られるだけです。
このツールは数の大きさから推測し、その推測を結果のすぐ横に伝えます。今日のエポック秒は 10 桁、今日のエポックミリ秒は 13 桁なので、推測はほぼ常に正しいのですが、これからバグ報告に貼り付けようとする値に「ほぼ」では足りません。だから解釈は常に見えていて、常にワンクリックで切り替えられます。
タイムゾーン、UTC、そして「ローカル」が曖昧な理由
Unix タイムスタンプにはタイムゾーンがありません。それは一つの瞬間を指し、1716197600 は 2024-05-20T09:33:20Z です。その同じ瞬間はロンドンでは 10:33、エルサレムでは 12:33、東京では 18:33 に同時になります。その日ロンドンとエルサレムは夏時間で、日本には夏時間がまったくないからです。タイムゾーンは値の一部ではなく、値を通して見るレンズです。
だからこのツールは複数のレンズを一度に表示します。UTC はすべてのサーバーとログが一致する中立の基準です。ローカル時刻はお使いの端末が報告するもので、ゾーン名 (Europe/Berlin など) を添えて表示するので、どのレンズが生んだ値かが常に分かります — 判定はブラウザ内で行われるため、ベルリンの訪問者にはベルリン時刻が、東京の訪問者には東京時刻が表示されます。3 行目は完全な IANA タイムゾーンデータベースから選んだ任意のゾーンで、別の場所にあるサーバーのログを読むときに欲しい行です。
- UTC — すべてのシステムが一致する基準で、保存とログに正しいものです。
- ローカル — お使いの端末が見るのと同じ瞬間で、判定したゾーンのラベル付きです。
- 任意に選んだゾーン — 他の場所のマシンのログやトレースを読むためのものです。
- ISO 8601 — 交換用のテキスト形式で、例えば 2024-05-20T09:33:20.000Z です。
- 相対 — 「3 時間前」など、どれくらい最近かを手早くつかむためのものです。
オフセット (+03:00、-04:00) は各時刻の横に表示されます。固定ではないからです: ほとんどのゾーンは夏時間のために 1 時間ずれるため、同じゾーンでも時期によって異なるオフセットを生みます。切り替わりの近くの日付こそ、手計算が誤る場所です。
実務でのエポック時刻の扱い
どの言語もシェルも、エポック値を作り読み取る独自の方法を持っています。覚えておく価値があるのは次のものです:
date +%s # シェル: 現在時刻を秒で date -d @1716197600 # シェル (GNU): 秒から日付へ Date.now() # JavaScript: 現在時刻をミリ秒で new Date(1716197600 * 1000) # JavaScript: 秒から Date へ time.time() # Python: 秒、浮動小数点で datetime.fromtimestamp(1716197600, tz=timezone.utc) SELECT EXTRACT(EPOCH FROM now()) -- PostgreSQL: 秒
ほとんどの日付の苦痛を避ける経験則: 瞬間は UTC として保存・送信し — エポック整数か ISO 8601 文字列で — ローカルのゾーンへの変換は、実際に誰かに表示する最後の瞬間まで行わないことです。早く書式化することが、タイムゾーンのバグを表示層にとどめずデータに焼き込む原因になります。
もう一つ知っておく価値のあること: 符号付き 32 ビットの秒カウンターは 2038 年 1 月 19 日に尽きます。「2038 年問題」です。現代のシステムは 64 ビット値を使い問題ありませんが、古い組み込み機器やレガシーなデータベース列は、まさにそれに出会いうる場所です。
エポックとは何か、そしてすべてのタイムスタンプが 1970 年から始まるわけではない理由
この意味でのエポックとは、単に選ばれたゼロ — カウンターが数え始めると定義された瞬間 — のことです。Unix エポックは 1970 年 1 月 1 日 00:00:00 UTC で、何かから導かれたのではなく、都合のよい切りのよい日付だったから選ばれました。この形式そのものがその日でなければならないと求めているわけではありません。初期の Unix ははるかに近いゼロから 60 分の 1 秒を数えており、第 3 版のマニュアルはそれが続かない理由をはっきり述べています — 32 ビットの 60 分の 1 秒は 2.26 年ごとの危機を保証する、つまりおよそ 828 日ごとです。同じ 32 ビットの整数秒なら 136 年、符号付きなら 68 年届きます。それが上に出てくる 2038 年の日付です。
この経緯こそ、長い数値を信用する前に確かめるべき理由です。ほかのシステムは別のゼロから別の分解能で数えており、その一つを Unix 秒として読むと、数時間ではなく数世紀ずれます。出会う可能性が高いのは次のものです:
- Windows FILETIME — 1601 年 1 月 1 日 UTC からの 100 ナノ秒刻みです。1000 万で割って 11644473600 を引くと Unix 秒になります。このガイド全体で使う瞬間 1716197600 は、その方式では 133606712000000000 です。
- .NET DateTime.Ticks — 同じ 100 ナノ秒刻みですが、西暦 1 年の初めから数えます。Unix エポック自体は 621355968000000000 刻みにあたり、割る前に引くべき数がこれです。
- Apple の基準日 — 2001 年 1 月 1 日 UTC からの秒で、Cocoa と Core Data が使います。978307200 を足すと Unix 秒になります: 1716197600 はそこでは 737890400 です。
- Excel のシリアル値 — 秒ではなく日で、1899 年 12 月 30 日から数えます。Excel が 1900 年をうるう年として扱うためですが、実際はそうではありませんでした。
- GPS 時刻 — 1980 年 1 月 6 日からの秒で、うるう秒を一度も飛ばさずに数えるため、GPS 時刻と UTC はもう一致しません。
最後の項目は、Unix の値そのものについて成り立つことを指しています: それはストップウォッチの読みではありません。POSIX はそれをエポックから経過した秒数に近い値と定義し、どの日もちょうど 86400 秒で数えることを求めています — つまり UTC に挿入されたうるう秒はまったく数えられません。したがって二つの Unix タイムスタンプの差は、実際に経過した秒数ではなくその間の暦の秒数であり、値は UTC の暦の読みの符号化と理解するのが最も適切です。どのタイムスタンプもうるう秒を指せないのも、そのためです。この符号化にはうるう秒の枠がありません。
日付からエポック値へ: シェル、JavaScript、Python
上のブロックはエポック値を読める形に変えます。逆方向 — すでに手元にある日付を、テキストであれ数値の組であれ、エポック値に変えること — こそタイムゾーンのバグが住む場所です。テキストがゾーンを名指ししないとき、ここに挙げるどれもが黙ってゾーンを仮定するからです。同じ仕事を三通りで、このガイドの瞬間 2024-05-20T09:33:20Z について示します。シェルの行は GNU の date です。BSD と macOS の date は別のオプションを取ります。
date -u -d '2024-05-20 09:33:20' +%s # 1716197600 — -u はテキストを UTC として読む date -d '2024-05-20 09:33:20 UTC' +%s # 同じこと、ゾーンをテキスト内で名指しする date -d '2024-05-20 09:33:20' +%s # どちらでもない: マシンのゾーン、別の瞬間
Date.parse('2024-05-20T09:33:20Z') / 1000 // 1716197600 — Z があるから UTC になる
new Date('2024-05-20T09:33:20Z').getTime() // 同じ瞬間をミリ秒で
Date.parse('2024-05-20 09:33:20') // Z なし: マシンのゾーン、別の瞬間from datetime import datetime, timezone
int(datetime(2024, 5, 20, 9, 33, 20, tzinfo=timezone.utc).timestamp()) # 1716197600 — タイムゾーンを持つ datetime
int(datetime.fromisoformat('2024-05-20T09:33:20+00:00').timestamp()) # 同じこと、文字列から解析
int(datetime(2024, 5, 20, 9, 33, 20).timestamp()) # ナイーブ: マシンのゾーン三つとも型は同じです: ゾーンを名指しするか、さもなければマシンの設定を受け継ぐかです。自分のノート PC では正しく同僚のものでは数時間ずれる数値は、ほぼ常にこれであり、だからこそ上のツールはどちらか一方を選ばずに UTC とローカルの読みを並べて表示します。すでに数値が手元にあって目で確かめたいなら、このページ上部の欄に貼り付けてください。
よくある質問
- 私の数値が秒かミリ秒かをどう判別しているのですか?
- その大きさからです: おおよそ 1e11 未満の値は秒として、それより大きければミリ秒として読みます。今日ではこれが 10 桁の秒と 13 桁のミリ秒をきれいに分けます。解釈は結果の横に表示され、ワンクリックで切り替えられるので、推測が隠されることはありません。
- 「ローカル」とはどのタイムゾーンですか?
- お使いの端末が報告するゾーンで、ブラウザ内で判定され、迷わないよう名前で表示されます。サイトのゾーンではなくあなたのゾーンです — ベルリンの訪問者にはベルリン時刻が、東京の訪問者には東京時刻が表示されます。
- 日付をタイムスタンプに戻せますか?
- はい。同じ欄が両方向を受け付けます: 数値を入力すれば日付が、2024-05-20 や 2024-05-20T09:33:20Z のような日付を入力すればエポック値が返ります。切り替えるモードはありません。
- 1970 年より前の日付も扱えますか?
- はい。エポックより前のタイムスタンプは単に負になり — -86400 は 1969 年 12 月 31 日です — 負の値も受け付けて通常どおり変換されます。
- タイムスタンプが思っていたのと違う日付を示すのはなぜですか?
- ほぼ常に二つの理由のどちらかです: 秒/ミリ秒の解釈が思い込みと違う (ラベルを確認して切り替えてください)、あるいは UTC の値をローカル時刻の期待と比べている、のいずれかです。このツールは両方の行を並べて表示するので、どちらかが分かります。
- 2038 年問題とは何ですか?
- エポック秒を符号付き 32 ビット整数で保存するシステムは、2038 年 1 月 19 日にあふれて負の数に折り返し、1901 年の日付を返します。64 ビット値を使うもの — 現代のほぼすべて — は影響を受けませんが、レガシーな組み込みシステムや古いデータベース列は今もリスクを抱えていることがあります。
- タイムスタンプが 18 桁あるのはなぜですか?
- おそらく Unix タイムスタンプではないからです。今日の Unix 秒は 10 桁、Unix ミリ秒は 13 桁です。18 桁は 100 ナノ秒刻みの見た目で、Windows FILETIME は 1601 年から、.NET は西暦 1 年の初めからそれを数えます。16 桁はもう一つのよくある場合で、同じ瞬間をマイクロ秒で表したものです。上のエポックの節に、それぞれ引くべき数があります。
- Python で日付を Unix タイムスタンプに変換するには?
- タイムゾーンを持つ datetime — tzinfo を備えたもの — を作り、その timestamp メソッドを呼び、結果を整数に切り捨てます。上のコードブロックにその行があり、同じ節がシェルと JavaScript でも同じ仕事を示します。難しさはすべて tzinfo にあります: それを省くと Python はあなたの数値をマシンのローカル時刻として読み、何も言わずに違う値を返します。
- 入力したタイムスタンプはどこかに送られますか?
- いいえ。解析・変換・書式化はすべて、プラットフォーム自身の日付とタイムゾーンのサポートを使ってブラウザ内で動きます。入力した内容が端末の外に出ることはありません。
関連するツール
- chmod パーミッション計算
ファイル権限を 8 進数・記号・チェックボックスで相互変換。
- CIDR / サブネット計算
ネットワークを分解し、所属を確認し、分割する。
- cron 式の解説ツール
cron 式を読み解き、実際に動く時刻を確認。
- 自分のIPアドレス
公開 IPv4 と IPv6、そしてブラウザが選んだほう。