Unix時間を日付に — 1行で
タスク全体を一例で示します。Unixタイムスタンプ1700000000は2023-11-14T22:13:20Z(2023年11月14日(火)22:13:20 UTC)になります。Unixタイムスタンプは1970年1月1日UTCからの秒数を数えるので、変換とはその数をUTCとしてデコードし、必要なタイムゾーンで整形することです。変換を壊す唯一の要因は単位です。10桁は秒、13桁はミリ秒、16桁はマイクロ秒です。下の表は、このガイドで扱う各言語・ツールのコピーしてすぐ使えるワンライナーです。
| 言語 / ツール | 関数 | 想定される単位 | デフォルトでUTC? |
|---|---|---|---|
| JavaScript | new Date(s * 1000) | ミリ秒 | いいえ — timeZoneオプションを渡す |
| Python | datetime.fromtimestamp(s, tz=timezone.utc) | 秒 | tzを設定した場合のみ |
| Java | Instant.ofEpochSecond(s) | 秒 | はい(InstantはUTC) |
| C# / .NET | DateTimeOffset.FromUnixTimeSeconds(s) | 秒 | はい(UTCオフセット) |
| Go | time.Unix(s, 0).UTC() | 秒 | .UTC()付きで |
| PHP | gmdate('c', s) | 秒 | はい(gm = UTC) |
| シェル (GNU) | date -u -d @s | 秒 | -u付きで |
| SQL (Postgres) | TO_TIMESTAMP(s) | 秒 | はい(TIMESTAMPTZ) |
| Excel / Sheets | =A1/86400 + DATE(1970,1,1) | 秒 | — |
Unix時間を日付に変換するとは
Unixタイムスタンプは1970年1月1日UTCからの秒数です。日付に変換するにはUTCとしてデコードし、任意のタイムゾーンで整形します。これが一文で表した問題のすべてで、ガイドの残りは各言語の構文にすぎません。すべての現代的なプログラミング言語は、Unixエポック値を受け取って日付オブジェクトを返す組み込み関数を備えています。注意すべき唯一の点は、その言語が秒(Python、PHP、Linuxのdate)、ミリ秒(JavaScriptのDate)、マイクロ秒(PostgreSQL、BigQuery)のどれを想定しているかです。
素早い変換ルール
値の桁数を数えます。10桁の数値はUnix秒です。13桁の数値はUnixミリ秒です。16桁の数値はUnixマイクロ秒です。Unixエポックは1970年1月1日に始まったため、現在(2026年)の10桁の値は17または18で始まり、ミリ秒は175または176に続けて10桁、マイクロ秒は1758または1759で始まります。変換関数に値を渡す前に単位を判別すれば、出力は1970年ではなく正しい日に収まります。
- 10桁 → Unix秒(範囲は2001年〜2286年)
- 13桁 → Unixミリ秒(範囲は2001年〜2286年)
- 16桁 → Unixマイクロ秒(範囲は2001年〜2286年)
- 10^9(1,000,000,000)付近の数値は2001年より前の秒 — それでも有効なUnix時間
- 負の整数は1970年より前の日付 — ほとんどの言語が扱うが要確認
- INT列で2^31を超える数値は2038年の上限に達する — 下記参照
JavaScriptでUnix時間を日付に変換する
JavaScriptのDateコンストラクタはミリ秒を想定するため、Unix秒の値はまず1000倍する必要があります。結果はDateオブジェクトです。UTCのISO 8601にはtoISOString()、タイムゾーンを考慮した人間可読の文字列にはIntl.DateTimeFormatで整形します。常に明示的なtimeZoneオプションを渡してください。これがないと、JavaScriptは実行環境のローカルタイムゾーンを使い、開発用PCと本番サーバーとで異なります。
- new Date(1700000000 * 1000).toISOString() // '2023-11-14T22:13:20.000Z'
- new Date(1700000000 * 1000).toLocaleString('en-US', { timeZone: 'America/New_York' }) // tz-aware
- new Date(1700000000000).toISOString() // milliseconds — no × 1000 needed
- new Intl.DateTimeFormat('en-US', { timeZone: 'Asia/Tokyo', dateStyle: 'full', timeStyle: 'long' }).format(new Date(ms))
- Detect unit at runtime: const toDate = ts => new Date(ts < 1e11 ? ts * 1000 : ts)
PythonでUnix時間を日付に変換する
datetime.fromtimestamp(ts, tz=timezone.utc) はPythonの正規の変換です。UTCの結果にはtz引数が必須で、これがないとPythonはシステムのローカルタイムゾーンでタイムスタンプを返します — サーバー上でのタイムゾーンずれのバグの頻出原因です。utcfromtimestamp() は誤用しやすいnaiveなdatetimeを返していたため、Python 3.12で非推奨になりました。ミリ秒は1000で、マイクロ秒は1,000,000で割ります。Pythonは小数秒を直接受け付けます。
- from datetime import datetime, timezone
- datetime.fromtimestamp(1700000000, tz=timezone.utc) # 2023-11-14 22:13:20+00:00
- datetime.fromtimestamp(1700000000.123, tz=timezone.utc) # fractional seconds work
- datetime.fromtimestamp(ms / 1000, tz=timezone.utc) # from milliseconds
- datetime.fromtimestamp(us / 1_000_000, tz=timezone.utc) # from microseconds
- Avoid: datetime.utcfromtimestamp(ts) — deprecated in 3.12; returns naive datetime
PHPでUnix時間を日付に変換する
PHPのgmdate(format, timestamp) は指定したUnix秒のUTC日付文字列を返します。date(format, timestamp) は同じ瞬間をサーバーのローカルタイムゾーン(date_default_timezone_setまたはphp.iniで制御)で返します。DateTimeZoneを伴うDateTimeクラスは、現代的でイミュータブルなAPIを提供し、任意のIANAタイムゾーン名をサポートします。PHPは既定で秒単位で動作するため、ミリ秒の値はまず1000で割ってください。
- gmdate('c', 1700000000) // '2023-11-14T22:13:20+00:00' (UTC ISO 8601)
- date('Y-m-d H:i:s', 1700000000) // server-local — depends on date.timezone setting
- new DateTime('@1700000000') // immutable, UTC by default with the @ prefix
- (new DateTime('@1700000000'))->setTimezone(new DateTimeZone('Asia/Tokyo'))->format('c')
- DateTime::createFromFormat('U.u', '1700000000.123456') // sub-second precision
JavaでUnix時間を日付に変換する
Javaのjava.time API(Java 8以降)は、Instant.ofEpochSecond(s) でUnix秒を変換し、UTCのインスタントを返します。Instantは常にUTCなので、ローカルタイムゾーンの隠れた落とし穴はありません。ミリ秒入力にはInstant.ofEpochMilli(ms)を使い、壁時計表示にはatZone(ZoneId.of(...))でゾーンを付与し、DateTimeFormatterで整形します。レガシーのjava.util.DateコンストラクタはJavaScriptと同様にミリ秒を想定するため、まず秒を1000L倍してください。
- Instant.ofEpochSecond(1700000000) // 2023-11-14T22:13:20Z (UTC)
- Instant.ofEpochMilli(1700000000000L) // from milliseconds
- Instant.ofEpochSecond(1700000000).atZone(ZoneId.of("Asia/Tokyo")) // tz-aware
- DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochSecond(s)) // ISO 8601
- new java.util.Date(1700000000L * 1000) // legacy API — expects milliseconds
C#(.NET)でUnix時間を日付に変換する
.NETでは、DateTimeOffset.FromUnixTimeSeconds(s) が現代的な変換で、UTC(+00:00)に固定されたDateTimeOffsetを返します。ミリ秒入力にはFromUnixTimeMilliseconds(ms)を使います。UTCのDateTimeには.UtcDateTimeを読み取り、特定のゾーンへの変換にはTimeZoneInfo.ConvertTimeを使います。ISO 8601にはラウンドトリップ指定子 "o" で整形します。組み込みのUnixメソッド(.NET 4.6で追加)がエポック計算を処理するため、古いDateTime.AddSeconds(1970年起点)のパターンは避けてください。
- DateTimeOffset.FromUnixTimeSeconds(1700000000) // 2023-11-14 22:13:20 +00:00
- DateTimeOffset.FromUnixTimeMilliseconds(1700000000000) // from milliseconds
- DateTimeOffset.FromUnixTimeSeconds(s).UtcDateTime // DateTime in UTC
- TimeZoneInfo.ConvertTime(dto, tzInfo) // tz-aware rendering
- DateTimeOffset.FromUnixTimeSeconds(s).ToString("o") // ISO 8601 round-trip
GoでUnix時間を日付に変換する
Goのtime.Unix(sec, nsec) はUnix秒(および任意のナノ秒)からTimeを構築しますが、値をローカルタイムゾーンで返すため、.UTC() を呼び出して固定します。Go 1.17でtime.UnixMilli(ms)とtime.UnixMicro(us)が追加され、手動で割る必要がなくなりました。ISO 8601にはRFC3339定数で整形し、特定のゾーンにはtime.LoadLocationと.In(loc)を使います。
- time.Unix(1700000000, 0).UTC() // 2023-11-14 22:13:20 +0000 UTC
- time.UnixMilli(1700000000000).UTC() // from milliseconds (Go 1.17+)
- time.UnixMicro(1700000000000000).UTC() // from microseconds (Go 1.17+)
- time.Unix(1700000000, 0).Format(time.RFC3339) // ISO 8601 string
- time.Unix(s, 0).In(loc) // tz-aware; loc from time.LoadLocation
シェル(Linux / macOS)でUnix時間を日付に変換する
LinuxではGNUのdateコマンドが -d @ts でUnix秒から変換し、macOSではBSDのdateコマンドが -r ts で同じ処理を行います。フラグは歴史的な実装によって異なりますが、エポック計算そのものは同一です。-u フラグはTZ環境変数に関わらずUTC出力を強制します。両実装とも +%FORMAT 引数で任意の出力形式に対応します。最も有用な書式文字列を下にまとめます。
- GNU (Linux): date -u -d @1700000000 // 'Tue Nov 14 22:13:20 UTC 2023'
- GNU: date -u -d @1700000000 +'%Y-%m-%dT%H:%M:%SZ' // ISO 8601 UTC
- BSD (macOS): date -u -r 1700000000 // same result, different flag
- BSD: date -u -r 1700000000 +'%Y-%m-%dT%H:%M:%SZ'
- Both: omit -u to use TZ environment variable; export TZ=America/New_York to override
- Sub-second: date -u -d @1700000000.123 +'%Y-%m-%dT%H:%M:%S.%3NZ' (GNU only)
SQL(Postgres、MySQL、SQLite、BigQuery)でUnix時間を日付に変換する
主要なSQL方言にはすべて、Unix秒(またはミリ秒、マイクロ秒)をネイティブのタイムスタンプ列に変換する組み込み関数があります。関数名は異なりますが、各関数が想定する単位は文書化され、データベース内で一貫しています。日付演算で手計算するのではなく、専用関数を使ってください。組み込み関数はうるう年、サブ秒精度、タイムゾーン変換を正しく処理します。
- PostgreSQL: TO_TIMESTAMP(1700000000) // returns TIMESTAMPTZ
- PostgreSQL: TO_TIMESTAMP(unix_us / 1000000.0) // for microsecond input
- MySQL: FROM_UNIXTIME(1700000000) // returns DATETIME in session timezone
- MySQL: CONVERT_TZ(FROM_UNIXTIME(ts), @@session.time_zone, 'UTC') // force UTC
- SQLite: datetime(1700000000, 'unixepoch') // returns TEXT 'YYYY-MM-DD HH:MM:SS'
- SQLite: datetime(ms / 1000, 'unixepoch') // from milliseconds
- BigQuery: TIMESTAMP_SECONDS(1700000000), TIMESTAMP_MILLIS(ms), TIMESTAMP_MICROS(us)
- ClickHouse: toDateTime(1700000000), fromUnixTimestamp(1700000000)
ExcelでUnix時間を日付に変換する
Excelは日付をシリアル値(1900年1月1日からの日数)として保存します。Unixタイムスタンプを Excelの日付に変換するのは単なる単位換算です。Unix秒を86,400(1日の秒数)で割り、1970年1月1日の日付を足し、セルを日付として書式設定します。数式 =A1/86400 + DATE(1970,1,1) が正規の答えで、すべての現代的なExcelで動作します。ミリ秒の場合は代わりに86,400,000で割ります。数式を入力したらセルを選択し、[セルの書式設定](Ctrl+1)を開き、[表示形式]タブで日付形式を選びます。
- Seconds: =A1/86400 + DATE(1970,1,1) // when A1 holds the Unix seconds value
- Milliseconds: =A1/86400000 + DATE(1970,1,1)
- Microseconds: =A1/86400000000 + DATE(1970,1,1)
- Format cell as Date after entering the formula (Ctrl+1 → Number → Date)
- Caveat: Excel's epoch is 1900-01-01, not 1970, hence the + DATE(1970,1,1) offset
- Reverse direction (date to Unix): =(A1 - DATE(1970,1,1)) * 86400
Google SheetsでUnix時間を日付に変換する
Google SheetsはExcelと同じ正規の数式を受け付け、さらに専用のEPOCHTODATE関数も提供します。短縮形は =EPOCHTODATE(A1, 1) で、第2引数は単位コードです(1 = 秒、2 = ミリ秒、3 = マイクロ秒)。出力はUTCに固定された日付で、Sheetsはシートのロケール設定に従って表示します。異なるタイムゾーンのチーム間で共有するシートでは、日付が表すべきタイムゾーンを列見出しに明記してください。
- =EPOCHTODATE(A1, 1) // seconds — shorthand
- =EPOCHTODATE(A1, 2) // milliseconds
- =EPOCHTODATE(A1, 3) // microseconds
- =A1/86400 + DATE(1970,1,1) // canonical formula — works in Sheets too
- Reverse direction: =(A1 - DATE(1970,1,1)) * 86400
- Time zone applied is the sheet's locale; check File → Settings → Time zone
UTC日付対ローカル日付 — どちらを表示するか
Unixタイムスタンプは瞬間をエンコードするもので、壁時計の表示ではありません。異なるタイムゾーンの2人の訪問者は、同じUnixタイムスタンプを異なる壁時計の日付として見ます。正しい挙動は日付が何を表すかによります。イベントログや監査記録はリージョン間比較のためUTCで表示すべきで、ユーザー向けの日付(締め切り、会議時刻、有効期限の通知)はユーザーのローカルタイムゾーンで表示すべきです。常にどちらかを選んで文書化し、すでにローカル時刻に変換した文字列を、その元のタイムゾーンも保存せずに保存しないでください。
- サーバーログ → UTCで表示し、列やグラフの軸に明示的にラベルを付ける
- ユーザー向けの締め切り → ユーザーのタイムゾーンで表示(Intl.DateTimeFormat().resolvedOptions().timeZone で自動検出)
- 繰り返しスケジュール(「毎週月曜午前9時 Eastern」) → ルールと一緒にタイムゾーンを保存し、実行のたびに次の瞬間を再計算する
- APIレスポンス → Zサフィックス付きISO 8601(UTC)が安全な既定。変換はクライアントに任せる
- データベース保存 → 常にUTC。変換は表示層でのみ行う
エッジケース:サブ秒精度、負のタイムスタンプ、2038年
3つのエッジケースが、それ以外は正しいコードをつまずかせます。マイクロ秒タイムスタンプ(16桁)は明示的な単位処理が必要で、秒として扱うと100万倍も未来の日付になります。負のUnixタイムスタンプは1970年より前の日付を表します。ほとんどの言語が扱いますが、Excel、Google Sheets、一部のSQL関数は1970年で頭打ちになるかエラーを返します。2038年問題は32ビット符号付き整数のオーバーフローで、2038-01-19 03:14:07 UTCに発生します。それ以降の値にはBIGINT保存または64ビットのtime_tが必要です。
- マイクロ秒(16桁) — 言語レベルの秒関数に渡す前に1,000,000で割る
- 負の秒 — 1970年より前の日付。JavaScript Date、Python datetime、PHP DateTimeはすべて扱える
- Excelでの負の秒 — #### または誤った日付になる。数式 =A1/86400 + DATE(1970,1,1) は正の値にのみ使う
- 2038年 — INTおよび符号付き32ビットのtime_tは2147483647 = 2038-01-19 03:14:07 UTCでオーバーフローする
- 2038年以降 — BIGINTで保存(符号付き64ビットはエポックの前後2920億年をカバー)
- Excelで1900年より前 — アプリに表示手段がない。テキストに変換するか、紀元前対応の上流ライブラリを使う
Unix時間を日付に変換する際のよくあるバグ
誰かが初めてUnix時間を日付に変換するたびに同じバグが現れます。結果が1970年になるのです。原因はほぼ常に、JavaScriptでの × 1000 の忘れ、Pythonでのtz引数の欠落、またはExcelによる数値列の自動切り捨てです。関連するバグの記事では10個すべてを取り上げており、どれもいずれUnix時間を変換するコードに現れます。一度目を通せば、その大半が本番に到達することはありません。
- 日付が1970年になる — ミリ秒が想定される場所に秒を渡した(JSのDateコンストラクタ)
- 日付がローカルUTCオフセットの分だけずれる — tz=timezone.utc(Python)またはtimeZoneオプション(JS)の指定を忘れた
- Excelが ##### または #VALUE! エラーを表示 — セルが日付として書式設定されていないか、値が負
- SQLのFROM_UNIXTIMEが誤った壁時計を返す — MySQLは@@session.time_zoneを適用する。UTCを明示的に強制する
- サーバーとノートPCで日付が異なる — システムのタイムゾーンが異なる。常にtzを明示的に渡す
FAQ
- Unixタイムスタンプから日付を取得するには?
- 値が秒(10桁)かミリ秒(13桁)かを判別し、各言語の組み込み変換を呼び出します。JavaScriptではnew Date(seconds * 1000)、Pythonではdatetime.fromtimestamp(seconds, tz=timezone.utc)、PHPではgmdate('c', seconds)、シェルではdate -u -d @seconds です。
- JavaScriptでUnixタイムスタンプから日付を取得するには?
- 秒の値を1000倍し(JavaScriptのDateコンストラクタはミリ秒を想定)、toISOString()またはIntl.DateTimeFormatで整形します。例:new Date(1700000000 * 1000).toISOString() は "2023-11-14T22:13:20.000Z" を返します。
- PythonでUnixタイムスタンプから日付を取得するには?
- datetime.fromtimestamp(unix_seconds, tz=timezone.utc) を使います。UTCの結果にはtz引数が必須で、これがないとPythonはシステムのローカルタイムゾーンでタイムスタンプを返します。utcfromtimestamp() はPython 3.12で非推奨です。
- Unix時間を日付に変換するには?
- 正しい単位(秒またはミリ秒)とUTCタイムゾーンを指定して、値を各言語の組み込みのエポック→datetime関数に渡します。結果は同じ瞬間を人間が読める日付として整形したものです。
- Linux時間はUnix時間と同じですか?
- はい。Linux、macOS、およびすべてのUnix系システムは同じエポック基準(1970年1月1日00:00:00 UTCからの秒数)を使います。dateコマンド、time()システムコール、clock_gettime() はすべてUnix時間を返します。
- なぜUnixタイムスタンプが1970年に変換されるのですか?
- ほぼ常に、ミリ秒を想定する関数に秒を渡したためです(または0 / nullが数値に変換された場合)。JavaScriptのnew Date(1700000000) は1970年1月になります。コンストラクタはミリ秒を想定するため、まず1000倍してください。
- ExcelでUnix時間を日付に変換するには?
- A1にUnix秒が入っている場合、=A1/86400 + DATE(1970,1,1) を使います。結果は[セルの書式設定]で日付として書式設定します。ミリ秒の場合は先に86400000で割ります:=A1/86400000 + DATE(1970,1,1)。
- Google SheetsでUnix時間を日付に変換するには?
- Excelと同じ正規の数式:=A1/86400 + DATE(1970,1,1)。Google Sheetsはより短い =EPOCHTODATE(A1, 1) も受け付けます。第2引数は単位です(1 = 秒、2 = ミリ秒、3 = マイクロ秒)。
- マイクロ秒のUnixタイムスタンプ(16桁)はどう扱いますか?
- 1,000,000で割って秒にしてから通常どおり変換します。Python 3.7+ は小数秒を直接受け付けます:datetime.fromtimestamp(unix_us / 1_000_000, tz=timezone.utc)。PostgreSQL TO_TIMESTAMP と BigQuery TIMESTAMP_MICROS はマイクロ秒をネイティブに扱います。