API レスポンスやデータベースのカラム、ログファイルに 1700000000 のような数値が並んでいることがあります。これは UNIX タイムスタンプ(POSIX タイム)と呼ばれる時刻の表現形式です。
この記事では、UNIX タイムスタンプとは何か・なぜ使われるのか・どう変換するのかを、プログラマー向けにわかりやすく解説します。
UNIX タイムスタンプとは
UNIX タイムスタンプとは、1970年1月1日 00:00:00 UTC(協定世界時)を起点(エポック)として、そこからの経過秒数を整数で表した値です。
例として、1700000000 という値は「1970年1月1日から 1,700,000,000 秒が経過した時刻」を意味します。これを変換すると 2023年11月14日 22:13:20 UTC(JST では 2023年11月15日 07:13:20)になります。
「UNIX 時間」「エポック秒」「POSIX タイム」とも呼ばれます。いずれも同じ概念を指します。
なぜ UNIX タイムスタンプが使われるのか
日時をシステム間でやりとりする場合、文字列(例: "2023-11-15 07:13:20")だとタイムゾーンの解釈や書式の違いによって誤りが生じやすくなります。UNIX タイムスタンプには以下のメリットがあります。
- タイムゾーンに依存しない: UTC 基準の絶対値なので、日本・アメリカ・ヨーロッパのどのサーバーで比較しても同じ値になる
- 計算が簡単: 2つの日時の差を求めるには引き算するだけ(例: 経過時間 = 現在のタイムスタンプ − 開始のタイムスタンプ)
- ソート可能: 数値が大きいほど新しい時刻なので、タイムスタンプをそのまま数値として比較・ソートできる
- コンパクト: 文字列より少ないバイト数で表現できる
秒単位とミリ秒単位の違い
UNIX タイムスタンプには 秒単位(10桁) と ミリ秒単位(13桁) の2種類があります。どちらを使っているかは桁数で判別できます。
| 種別 | 桁数 | 例 | 精度 |
|---|---|---|---|
| 秒単位 | 10桁 | 1700000000 | 1秒単位 |
| ミリ秒単位 | 13桁 | 1700000000000 | 1ミリ秒単位 |
秒単位からミリ秒単位に変換するには 1,000 を掛けます。ミリ秒単位から秒単位に変換するには 1,000 で割ります(小数点以下切り捨て)。
// 秒 → ミリ秒
const ms = 1700000000 * 1000; // 1700000000000
// ミリ秒 → 秒
const sec = Math.floor(1700000000000 / 1000); // 1700000000
各言語でのタイムスタンプ取得方法
| 言語 | 現在のタイムスタンプ取得 | 単位 |
|---|---|---|
| JavaScript | Date.now() | ミリ秒 |
| JavaScript | Math.floor(Date.now() / 1000) | 秒 |
| Python | import time; time.time() | 秒(浮動小数点) |
| Python | int(time.time()) | 秒(整数) |
| Go | time.Now().Unix() | 秒 |
| Go | time.Now().UnixMilli() | ミリ秒 |
| PHP | time() | 秒 |
| Ruby | Time.now.to_i | 秒 |
| SQL (MySQL) | UNIX_TIMESTAMP() | 秒 |
| SQL (PostgreSQL) | EXTRACT(EPOCH FROM NOW()) | 秒 |
タイムスタンプと日時の変換
JavaScript での変換
// タイムスタンプ → 日時(JST)
const ts = 1700000000;
const date = new Date(ts * 1000);
console.log(date.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' }));
// → "2023/11/15 7:13:20"
// 日時 → タイムスタンプ
const d = new Date('2023-11-15T07:13:20+09:00');
console.log(Math.floor(d.getTime() / 1000));
// → 1700000000
Python での変換
from datetime import datetime, timezone, timedelta
# タイムスタンプ → 日時(JST)
ts = 1700000000
JST = timezone(timedelta(hours=9))
dt = datetime.fromtimestamp(ts, tz=JST)
print(dt) # 2023-11-15 07:13:20+09:00
# 日時 → タイムスタンプ
import time
dt_str = '2023-11-15 07:13:20'
ts = int(datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
.replace(tzinfo=JST).timestamp())
print(ts) # 1700000000
JWT の exp フィールドを読む
JWT(JSON Web Token)の認証トークンには、有効期限を示す exp フィールドが含まれています。この値は UNIX タイムスタンプ(秒単位) です。
{
"sub": "user-123",
"iat": 1699999000,
"exp": 1700085400
}
上の例では exp: 1700085400 が有効期限です。タイムスタンプ変換ツールで確認すると「2023年11月16日 07:10:00 JST」などと読み解けます。
現在のタイムスタンプと比較して exp の値が小さければ、トークンは有効期限切れです。
const now = Math.floor(Date.now() / 1000);
const isExpired = now > jwtPayload.exp;
console.log(isExpired ? "期限切れ" : "有効");
2038年問題
UNIX タイムスタンプを 32 ビット符号付き整数で保存しているシステムでは、2038年1月19日 03:14:07 UTC にオーバーフローが発生します。この値を超えると、多くのシステムで日時が 1901年に戻る現象が起きます(いわゆる「2038年問題」)。
現代のシステムでは 64 ビット整数を使うことでこの問題は回避されていますが、古いシステムや組み込みデバイスでは依然として潜在的なリスクが残っています。
まとめ
- UNIX タイムスタンプは 1970年1月1日 00:00:00 UTC からの経過秒数
- 10桁 = 秒単位、13桁 = ミリ秒単位で区別できる
- タイムゾーンに依存しないため、システム間でのやりとりに適している
- JWT の
expフィールドや API レスポンスで頻繁に登場する - 変換ツールを使えば、数値から人間が読める日時に即座に変換できる