UNIX時刻⇔日時変換|エポック秒/ミリ秒 タイムスタンプ相互変換
UNIX時刻(エポック秒・ミリ秒)と人間可読の日時を相互変換する無料電卓。1970年1月1日0時UTC(エポック元期)からの経過秒数として、Web/データベース/ログ解析/API通信で世界標準の時間表現を、瞬時にJST(日本時間)やISO 8601形式に変換。Date.now()・time()・strftime・SELECT UNIX_TIMESTAMP()で得られる値の確認、2038年問題(Y2K38)への対策、うるう秒、タイムゾーン変換、Excelシリアル値との違い、JWT の exp/iat/nbf検証まで、Web/DBエンジニア・データ分析者・システム運用担当者向けに6000字級で網羅したIT実務の必携ツールです。
UNIX時刻⇔日時ツール
UNIX時刻の定義と計算式
UNIX時刻(POSIX時間・エポック秒)は、協定世界時(UTC)1970年1月1日0時0分0秒からの経過秒数として時刻を表現する方式。POSIX(IEEE 1003.1)で標準化され、UNIX/Linux/macOS/Windows/Web/データベース、ほぼ全てのシステムで採用されています。
基本の変換式
UNIX秒 = (対象日時UTC − 1970/01/01 00:00:00 UTC) の秒数
1秒 = 1,000 ミリ秒(ms)= 1,000,000 マイクロ秒(μs)= 1,000,000,000 ナノ秒(ns)
JST(日本時間) = UTC + 9時間
1日 = 86,400秒
1年 = 31,536,000秒(うるう年365日は31,622,400秒)
ISO 8601形式との対応
UNIX秒 1700000000
= 2023-11-15T06:13:20Z(UTC / ISO 8601)
= 2023-11-15T15:13:20+09:00(JST)
= 2023-11-15 15:13:20(人間可読・JST)
ISO 8601は国際標準の日時表記形式。末尾Z=UTC、+09:00=JSTで明示。JSON API・ログ形式で推奨されます。
エポック元期と歴史的背景
1970年1月1日0時UTCが起点となった理由は、UNIXがベル研究所で1969-1970年に開発された時期に近い「切りの良い日」を選んだためと言われます。当時の32bit符号付き整数の範囲(±2^31=約68年)で1902-2038年をカバーできる設計判断でした。
1971年発表の初期UNIX時代は1/60秒単位(tick)で計測していましたが、後に秒単位に整理され現在に至ります。
他のエポック採用例
| システム | エポック起点 | 単位 |
|---|---|---|
| UNIX/POSIX(多くのシステム) | 1970-01-01 00:00 UTC | 秒 |
| JavaScript(Date.now()) | 1970-01-01 00:00 UTC | ミリ秒 |
| Java(System.currentTimeMillis) | 1970-01-01 00:00 UTC | ミリ秒 |
| .NET DateTime.Ticks | 0001-01-01 00:00 UTC | 100ナノ秒 |
| Excel(Windows版) | 1900-01-01 | 日 |
| Excel(Mac版・旧) | 1904-01-01 | 日 |
| Windows FILETIME | 1601-01-01 00:00 UTC | 100ナノ秒 |
| Cocoa NSDate | 2001-01-01 00:00 UTC | 秒(Double) |
| GPS時刻 | 1980-01-06 00:00 UTC | 秒(うるう秒無視) |
言語別の取得方法
| 言語・環境 | 現在時刻取得 | 単位 |
|---|---|---|
| JavaScript | Date.now() | ミリ秒 |
| JavaScript(秒) | Math.floor(Date.now()/1000) | 秒 |
| Python | import time; time.time() | 秒(float) |
| Python(整数秒) | int(time.time()) | 秒 |
| PHP | time() | 秒 |
| PHP(ミリ秒) | (int)(microtime(true)*1000) | ミリ秒 |
| Ruby | Time.now.to_i | 秒 |
| Java | System.currentTimeMillis() | ミリ秒 |
| C言語 | time(NULL) | 秒(time_t) |
| Go | time.Now().Unix() | 秒 |
| Swift | Date().timeIntervalSince1970 | 秒(Double) |
| MySQL | SELECT UNIX_TIMESTAMP() | 秒 |
| PostgreSQL | SELECT EXTRACT(EPOCH FROM NOW()) | 秒 |
| Bash | date +%s | 秒 |
| Bash(ミリ秒) | date +%s%3N | ミリ秒 |
| PowerShell | [int](Get-Date -UFormat %s) | 秒 |
JavaScriptとJavaはミリ秒基準、Python/PHP/Ruby/Go/C/DBは秒基準が主流。桁数13なら ms、10なら秒と判別できます(2001年〜2286年の場合)。
歴史的なUNIX時刻マイルストーン
| UNIX秒 | UTC日時 | 意味 |
|---|---|---|
| 0 | 1970-01-01 00:00:00 | エポック元期 |
| 1,000,000 | 1970-01-12 13:46:40 | 約12日後 |
| 100,000,000 | 1973-03-03 09:46:40 | 1億秒(3年3ヶ月) |
| 1,000,000,000 | 2001-09-09 01:46:40 | 10億秒(31年8ヶ月) |
| 1,234,567,890 | 2009-02-13 23:31:30 | 語呂合わせで話題 |
| 1,500,000,000 | 2017-07-14 02:40:00 | 15億秒 |
| 1,600,000,000 | 2020-09-13 12:26:40 | 16億秒 |
| 1,700,000,000 | 2023-11-15 06:13:20 | 17億秒 |
| 1,800,000,000 | 2027-01-15 08:00:00 | 18億秒 |
| 2,000,000,000 | 2033-05-18 03:33:20 | 20億秒 |
| 2,147,483,647 | 2038-01-19 03:14:07 | 2038年問題(Y2K38) |
| 2,147,483,648 | 2038-01-19 03:14:08 | 32bit signed intオーバーフロー |
| 4,294,967,295 | 2106-02-07 06:28:15 | 32bit unsigned intの上限 |
タイムゾーン変換
UNIX時刻はタイムゾーン非依存の絶対時刻ですが、人間可読形式に変換する際にタイムゾーンを指定します。
主要都市のUTCオフセット
| 都市・地域 | UTCオフセット | UNIX 1700000000 |
|---|---|---|
| UTC(協定世界時) | +0:00 | 2023-11-15 06:13:20 |
| ロンドン(GMT) | +0:00 / +1:00夏 | 2023-11-15 06:13:20 |
| パリ・ベルリン(CET) | +1:00 / +2:00夏 | 2023-11-15 07:13:20 |
| モスクワ(MSK) | +3:00 | 2023-11-15 09:13:20 |
| ドバイ(GST) | +4:00 | 2023-11-15 10:13:20 |
| インド(IST) | +5:30 | 2023-11-15 11:43:20 |
| バンコク(ICT) | +7:00 | 2023-11-15 13:13:20 |
| 北京・シンガポール(CST/SGT) | +8:00 | 2023-11-15 14:13:20 |
| 東京・ソウル(JST/KST) | +9:00 | 2023-11-15 15:13:20 |
| シドニー(AEST) | +10:00 / +11:00夏 | 2023-11-15 16:13:20 |
| ハワイ(HST) | −10:00 | 2023-11-14 20:13:20 |
| ロサンゼルス(PST) | −8:00 / −7:00夏 | 2023-11-14 22:13:20 |
| ニューヨーク(EST) | −5:00 / −4:00夏 | 2023-11-15 01:13:20 |
日本は夏時間なし・UTC+9固定のため計算が単純。欧米は夏時間の切替(3月・11月)で日時計算にバグが出やすいので、システム設計時はDBには UNIX秒(UTC)で保存し、表示時にタイムゾーン変換が定石です。
2038年問題(Y2K38)
1970年から2^31=2,147,483,648秒後 = 2038年1月19日3時14分07秒UTCに、32bit符号付き整数(signed int32)でUNIX秒を保持しているシステムがオーバーフローし、内部で負の数(1901年12月13日)になる問題。
影響を受けるシステム
- 組み込み機器:ルーター・産業機器・自動車ECU・古い医療機器
- 旧UNIX/古いLinuxカーネル:32bit環境での time_t
- MySQL 5.1以前の TIMESTAMP:2038年上限
- PHP 5.x(32bit環境):strtotime()関数の上限
- 古いExcel・DBのタイムスタンプ列
対策状況
主要なOS・言語では既に64bit time_t対応済みです。2^63秒=約2920億年で事実上無限。ただしBIOSの日付・産業機器・レガシーシステムは今も対策が必要。Linux Kernel 5.6以降で32bit環境向けにも64bit対応が入り、2020年代前半に主要OS対応は完了しました。
うるう秒の扱い
地球の自転速度は微妙に変動するため、UTCと世界時UT1のずれが±0.9秒を超えないよう、時々うるう秒(Leap Second)が挿入されます。1972年以降、37回挿入されました(全て正のうるう秒、直近は2016年12月)。
POSIXの扱い
UNIX時刻は「1日=86,400秒」と規定しているため、うるう秒は無視される設計です。うるう秒挿入時には、同じUNIX秒値が2秒繰り返される「smearing」で調整されます(GoogleやFacebookは1日かけて緩やかに調整)。
2035年までにうるう秒を廃止することが国際度量衡総会(CGPM)で2022年に決議され、以降は不定期挿入が停止されます。
Excelシリアル値との違い
Excelは独自の日時管理を採用しており、UNIX時刻とは互換性がないため、データ移行時に変換が必要です。
変換式
Excel(Windows)シリアル → UNIX秒
UNIX秒 = (Excelシリアル − 25569) × 86400
※25569 = 1900-01-01から1970-01-01までの日数
Excel 1900-02-29問題:Excelは1900年が閏年と誤認しているため、1900/2/28以前の日付は1日ずれます。
| 日時 | UNIX秒 | Excelシリアル |
|---|---|---|
| 1900-01-01 00:00 UTC | −2,208,988,800 | 1 |
| 1970-01-01 00:00 UTC | 0 | 25569 |
| 2000-01-01 00:00 UTC | 946,684,800 | 36526 |
| 2023-11-15 06:13:20 UTC | 1,700,000,000 | 45245.259 |
JWT・API認証での活用
JWT(JSON Web Token)のペイロードには、iat(発行時刻)・exp(有効期限)・nbf(有効開始時刻)が全てUNIX秒で格納されます。
🔐 exp(有効期限)
JWTの失効時刻。現在UNIX秒 > exp なら期限切れとサーバー側で判定。exp = time() + 3600で1時間有効なトークンを発行するのが典型パターン。
📆 iat(発行時刻)
JWT発行時のUNIX秒。ログ追跡・監査・トークンローテーション判定に使用。iat と exp の差が JWT有効期間になります。
⏰ nbf(Not Before)
有効開始時刻。現在UNIX秒 < nbf ならまだ無効と判定。予約発行、スケジュールされたアクセス許可に使用します。
🔄 API リクエスト署名
AWS・Google Cloud・多くのAPIで、リクエストにタイムスタンプを含めHMAC署名。±5分以内のズレを許容し、リプレイ攻撃防止に活用されます。
よくある間違い・注意点
- 秒とミリ秒の桁数混同 — JavaScriptのDate.now()は13桁のミリ秒、Python/PHPのtime()は10桁の秒。10桁を「ミリ秒」と誤解して1000倍のズレが発生するバグが頻発します。桁数で自動判別する処理を入れましょう。
- ローカルタイムでDBに保存 — MySQLのDATETIME型でJSTを保存すると、海外展開時にタイムゾーン変換で混乱します。UNIX秒(またはTIMESTAMP型 UTC)でDB保存し、表示時に変換するのが定石です。
- 32bit環境での2038年問題 — 組み込み・ルーター・古いLinux/PHPは32bit signed intでUNIX秒を保持し、2038年1月19日にオーバーフローします。10年後を見据えて64bit対応が必須。
- うるう秒無視で1秒ズレ — GPS時刻とUTCは18秒(2024年時点)のずれがあります。GPS時刻はうるう秒を無視するため、GPS→UTC変換時にオフセット加算が必要です。高精度時刻同期システムでの注意点。
- タイムゾーン変換をクライアント側で実施 — ブラウザのタイムゾーン設定がユーザーごとに違うため、サーバー側で正規化しないとログの時系列が狂います。サーバー側でUTC保存・クライアントで表示変換を徹底してください。
- ExcelとUNIXの日時変換で1日ズレ — Excelは1900年を閏年と誤認しているバグを保持しており、1900/2/28以前の日付は1日ずれます。1970年以降なら通常の変換式で問題なしですが、古いデータは要注意。
- ミリ秒精度以上を要求する処理 — UNIX秒(整数)では1秒未満の精度を表現できません。ログ順序・レース条件検証にはナノ秒精度(time.time_ns()、performance.now())を使用してください。
参考文献・公的資料(発リンク)
UNIX時刻・タイムスタンプ・時刻同期については、以下の一次資料を参照してください。
- POSIX.1-2017 4.16 Seconds Since the Epoch ― UNIX時刻の公式定義(IEEE Std 1003.1-2017)。
- RFC 3339 - Date and Time on the Internet ― ISO 8601ベースのインターネット標準日時形式。
- RFC 7519 - JSON Web Token (JWT) ― exp/iat/nbfのUNIX秒使用仕様。
- ISO 8601 日付・時刻表記 ― 国際標準の日付・時刻表記法。
- 情報通信研究機構(NICT) 日本標準時プロジェクト ― JST・NTPサーバー・うるう秒公式情報。
- 国際度量衡局(BIPM) UTC ― UTC・うるう秒の国際管理。
- 国際地球回転・基準系事業(IERS) 公報 ― うるう秒発表機関の公式ブレティン。
- MDN Web Docs Date ― JavaScriptのDate/Date.now()仕様。
- Python公式 time モジュール ― time()/time_ns()等の仕様。
- MySQL 8.0 DATETIME/TIMESTAMP ― TIMESTAMP型の2038年上限とUTC変換仕様。
よくある質問(FAQ)
JavaScriptの時刻はなぜミリ秒?
Date.now()やnew Date().getTime()は1970年1月1日UTCからのミリ秒数を返します。桁数13。秒に変換するには1000で割る:Math.floor(Date.now()/1000)。ミリ秒精度はブラウザ・DBログの時系列を正確に扱うため。一部ブラウザではセキュリティ上、精度が5μs〜1ms程度に丸められています。
2038年問題(Y2K38)とは?
2038年1月19日3時14分07秒UTCに、32bit符号付き整数でUNIX秒を保持しているシステムがオーバーフローし、1901年12月13日に戻る問題。主要OS・言語は既に64bit対応済みですが、組み込み機器・産業ECU・ルーター・古いLinuxでは今も対策必要。BIOS・IoT機器は要注意です。
秒とミリ秒はどう見分ける?
2001年〜2286年の日時なら、秒は10桁・ミリ秒は13桁で判別可能。if (value > 10000000000) { /* ミリ秒 */ }のように閾値10^10で判定するのが一般的。逆にマイクロ秒(16桁)・ナノ秒(19桁)まで拡張する場合は桁数マッピングを増やします。
タイムゾーンの扱い方は?
UNIX時刻はタイムゾーン非依存の絶対時刻。DBには常にUTC(UNIX秒 or TIMESTAMP UTC)で保存し、表示時にクライアント/サーバーでローカルタイムに変換するのが定石。JST変換はnew Date(unixSec*1000).toLocaleString('ja-JP',{timeZone:'Asia/Tokyo'})のような形で。
うるう秒はUNIX時刻にどう影響?
POSIXは「1日=86,400秒」と規定しているためUNIX時刻はうるう秒を無視します。うるう秒挿入時は同じUNIX秒値が2秒繰り返されるか、Google/Facebookのように1日かけて緩やかに時刻を歪める(smearing)方法で対応。2035年までにうるう秒廃止決定済みなので今後は問題減少します。
GPS時刻とUNIX時刻の違いは?
GPS時刻は1980年1月6日UTC起点でうるう秒を無視するため、UTCと18秒ずれています(2024年現在)。UNIX時刻はUTC準拠なのでGPS時刻とは異なります。GPSデバイスの時刻をシステムに取り込む際は、GPS→UTC変換の18秒オフセット加算が必要です。
ExcelとUNIX時刻の変換方法は?
Excel(Windows版)のシリアル値は1900-01-01=1で日数単位。UNIX秒 = (Excelシリアル - 25569) × 86400で変換。ただしExcelは1900年を閏年と誤認するバグを保持しているため、1900/2/28以前は1日ズレます。1970年以降のデータなら問題なく変換可能です。
ISO 8601形式に変換するには?
JavaScriptならnew Date(unixSec*1000).toISOString()で「2023-11-15T06:13:20.000Z」を取得。末尾Zがつくとその時刻はUTCを示します。JST(+09:00オフセット付き)の場合はライブラリ(date-fns、Luxon、dayjs等)を使うと簡単です。API・ログ形式ではISO 8601が国際標準として推奨されます。
MySQLでUNIX時刻を扱うには?
UNIX_TIMESTAMP()で現在秒取得、FROM_UNIXTIME(unix_sec)で日時変換。TIMESTAMP型は自動でUTC⇔ローカル変換しますが、DATETIME型はタイムゾーン非依存で保存値をそのまま扱います。グローバル運用ならUNIX秒(BIGINT)保存が最も安全で、タイムゾーン問題が発生しません。
JWTのexp検証はどう実装?
サーバー側でif (currentUnixSec > jwt.exp) { throw '期限切れ' }のように判定。iat(発行時刻)とexp(有効期限)の差でJWT有効期間が決まります。典型的な設定:アクセストークン15分〜1時間、リフレッシュトークン7日〜30日。時刻同期(NTP)が狂っていると誤判定が起きるため、サーバーはNTP同期必須。
ナノ秒精度の時刻を扱うには?
Python 3.7+のtime.time_ns()、JavaScriptのperformance.now()(ミリ秒+マイクロ秒精度)、Java 8+のInstant.now().toEpochMilli()等でナノ秒/マイクロ秒精度を取得。ログ順序・レース条件検証・パフォーマンス計測で必須ですが、OS/ハードウェア精度で実際の分解能は制限されます。
負のUNIX時刻は使える?
負のUNIX時刻は1970年1月1日より前の日時を表します。例:−86400 = 1969-12-31 00:00 UTC。JavaScript・Python・Javaは負の値もサポートし、歴史的年月日の計算に使えます。ただし古い32bit signed intでは1901年12月13日20:45:52が下限。1900年以前の日付処理は専用ライブラリ推奨。