Java System.currentTimeMillis() ガイド
JavaでのUnix timestamp操作ガイド。System.currentTimeMillis()、Instant、java.time APIを使った変換方法とベストプラクティスを解説。
Language
System.currentTimeMillis()
詳細な説明
Javaには、レガシーなSystem.currentTimeMillis()からJava 8で導入されたモダンなjava.time APIまで、Unix timestampを扱う複数の方法があります。レガシーコードベースではまだ古いアプローチが広く使われているため、両方の理解が不可欠です。
現在のtimestampの取得:
// epochからのミリ秒(レガシーアプローチ)
long ms = System.currentTimeMillis(); // 1700000000000L
// epochからの秒(java.time)
long sec = Instant.now().getEpochSecond(); // 1700000000L
// ミリ秒(java.time)
long ms2 = Instant.now().toEpochMilli(); // 1700000000000L
timestampと日付の相互変換:
// timestamp → Instant
Instant instant = Instant.ofEpochSecond(1700000000L);
Instant instantMs = Instant.ofEpochMilli(1700000000000L);
// Instant → ZonedDateTime
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/New_York"));
// フォーマット
String iso = instant.toString(); // "2023-11-14T22:13:20Z"
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = zdt.format(fmt);
レガシーDateクラス(新規コードでは避けるべき):
// 旧アプローチ — 今でもいたるところで見られる
Date date = new Date(1700000000000L); // ミリ秒を期待
long timestamp = date.getTime();
// 旧APIと新APIの変換
Instant fromDate = date.toInstant();
Date fromInstant = Date.from(instant);
よくある落とし穴:
JavaのSystem.currentTimeMillis()は秒ではなくミリ秒を返します。PythonやCから来た開発者がつまずきやすいポイントです。さらに、レガシーのjava.util.Dateクラスはミュータブルでスレッドセーフではありません。Instantとjava.time APIを推奨するもう一つの理由です。
ナノ秒精度: JavaのInstantは内部的にナノ秒精度をサポートしていますが、System.currentTimeMillis()はミリ秒の粒度しか提供しません。より高い分解能には、JDK 9以降のInstant.now()を使用してください。ほとんどのプラットフォームでデフォルトクロックがマイクロ秒精度を提供します。ベンチマークにはSystem.nanoTime()を使用してください。壁時計の調整とは独立した経過時間を計測します。
ユースケース
Javaのtimestampは、エンタープライズシステムにおけるトランザクションIDの生成、キャッシュエビクションポリシーの設定、OAuth 2.0認可サーバーでのトークンライフタイムの計算に不可欠です。