この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 日時API
SEOタイトル: Java 日時 API 完全ガイド(java.time / LocalDate / Instant / Duration / 旧 Date と比較)

この記事の要点
  • Java 8 で導入された java.time パッケージが現代の標準。旧 java.util.Date はレガシー扱い
  • 主要型: LocalDate (日付) / LocalTime (時刻) / LocalDateTime (日時) / ZonedDateTime (タイムゾーン付)
  • 機械時刻: Instant (UTC 上の瞬間、エポック秒) / Duration (時間量)
  • 人間時刻量: Period (日/月/年単位)
  • フォーマット: DateTimeFormatter — ISO 標準 + 任意パターン両対応
  • スレッドセーフ & イミュータブル — 旧 SimpleDateFormat のスレッド問題から解放

Java の日時 API 全体像

Java の日時を扱う API はJava 8 を境に大きく変わりました。古い java.util.Date / Calendar / SimpleDateFormat は使いづらく、スレッドセーフでない問題もあり、Java 8 でjava.time パッケージ (JSR-310) が導入されました。

世代主要クラス用途
旧 (Java 1.0〜)Date / Calendarレガシーコード互換
旧フォーマットSimpleDateFormatスレッドアンセーフ
新 (Java 8〜)java.time.*新規コードは全部こちら

java.time の主要クラス

クラス意味
LocalDate日付(年月日)2026-06-11
LocalTime時刻(時分秒)14:30:00
LocalDateTime日時(TZ なし)2026-06-11T14:30:00
ZonedDateTimeタイムゾーン付き日時2026-06-11T14:30+09:00[Asia/Tokyo]
OffsetDateTimeUTC オフセット付き2026-06-11T14:30+09:00
InstantUTC タイムスタンプ2026-06-11T05:30:00Z
Duration時間量(秒・ナノ秒)PT2H30M
Period期間(年月日)P1Y2M3D
Year / Month / YearMonth / MonthDay部分日付2026 / JUNE / 2026-06 / 06-11
DayOfWeek曜日THURSDAY
ZoneIdタイムゾーンAsia/Tokyo
DateTimeFormatter整形・パース"yyyy/MM/dd"

基本操作

import java.time.*;
import java.time.format.DateTimeFormatter;

// 現在時刻
LocalDate today      = LocalDate.now();         // 2026-06-11
LocalTime nowTime    = LocalTime.now();         // 14:30:25.123
LocalDateTime now    = LocalDateTime.now();
ZonedDateTime zoned  = ZonedDateTime.now();
Instant instant      = Instant.now();           // UTC ベース

// 任意日時を作る
LocalDate date = LocalDate.of(2026, 6, 11);
LocalTime time = LocalTime.of(14, 30, 0);
LocalDateTime dt = LocalDateTime.of(2026, 6, 11, 14, 30);

// 文字列からパース (ISO-8601)
LocalDate d = LocalDate.parse("2026-06-11");
LocalDateTime dt2 = LocalDateTime.parse("2026-06-11T14:30:00");

// プロパティ取得
int year = date.getYear();      // 2026
Month month = date.getMonth();  // JUNE
int day = date.getDayOfMonth(); // 11
DayOfWeek dow = date.getDayOfWeek(); // THURSDAY

加減算 (immutable)

java.time のクラスは不変オブジェクトです。plus / minus は新しいインスタンスを返します。

LocalDate today = LocalDate.now();

LocalDate tomorrow = today.plusDays(1);
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate nextYear = today.plusYears(1);

LocalDate yesterday = today.minusDays(1);

// withXxx で値を差し替え
LocalDate firstOfMonth = today.withDayOfMonth(1);
LocalDate endOfYear    = today.withMonth(12).withDayOfMonth(31);

// TemporalAdjusters で柔軟に
import static java.time.temporal.TemporalAdjusters.*;

LocalDate nextMonday = today.with(next(DayOfWeek.MONDAY));
LocalDate lastDayOfMonth = today.with(lastDayOfMonth());
LocalDate firstDayOfYear = today.with(firstDayOfYear());

比較

LocalDate a = LocalDate.of(2026, 1, 1);
LocalDate b = LocalDate.of(2026, 6, 11);

boolean before = a.isBefore(b);   // true
boolean after  = a.isAfter(b);    // false
boolean equal  = a.isEqual(b);    // false
int cmp = a.compareTo(b);          // 負の値

差分 (Duration / Period)

// 日数の差 (Period: 年月日単位)
LocalDate start = LocalDate.of(2026, 1, 1);
LocalDate end   = LocalDate.of(2026, 6, 11);

Period p = Period.between(start, end);
System.out.println(p.getMonths() + "ヶ月" + p.getDays() + "日");
// 5ヶ月10日

long days = ChronoUnit.DAYS.between(start, end);   // 161

// 時間の差 (Duration: 秒・ナノ秒)
LocalTime t1 = LocalTime.of(9, 0);
LocalTime t2 = LocalTime.of(17, 30);
Duration d = Duration.between(t1, t2);
System.out.println(d.toHours() + "時間" + (d.toMinutes() % 60) + "分");
// 8時間30分

フォーマット (DateTimeFormatter)

LocalDateTime now = LocalDateTime.now();

// ISO 標準
String iso = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
// 2026-06-11T14:30:00

// カスタムパターン
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String s = now.format(fmt);          // 2026/06/11 14:30:00

// 日本語ロケール
DateTimeFormatter jp = DateTimeFormatter.ofPattern("yyyy年M月d日(E)", Locale.JAPAN);
String s2 = now.format(jp);          // 2026年6月11日(木)

// パース
LocalDateTime parsed = LocalDateTime.parse("2026/06/11 14:30:00", fmt);

パターン記号

記号意味
y2026 / 26
M月 (数値)06 / 6
MMM月 (短縮名)Jun / 6月
d11
H時 (24時間)14
h時 (12時間)02
m30
s00
E曜日 (短縮)Thu / 木
EEEE曜日 (完全)Thursday / 木曜日
aAM/PMPM
zタイムゾーンJST

タイムゾーン

// 日本時間
ZoneId tokyo = ZoneId.of("Asia/Tokyo");
ZonedDateTime ztokyo = ZonedDateTime.now(tokyo);

// UTC
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);

// タイムゾーン変換
ZonedDateTime ny = ztokyo.withZoneSameInstant(ZoneId.of("America/New_York"));
// 同じ瞬間を NY 時間で表現

// 利用可能なタイムゾーン一覧
Set zones = ZoneId.getAvailableZoneIds();

旧 API との変換

// java.util.Date ⇔ Instant
Date d = new Date();
Instant i = d.toInstant();
Date d2 = Date.from(i);

// Date ⇔ LocalDateTime
LocalDateTime ldt = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
Date d3 = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

// java.sql.Date / Time / Timestamp ⇔ LocalDate / LocalTime / LocalDateTime
LocalDate ld = new java.sql.Date(System.currentTimeMillis()).toLocalDate();
LocalDateTime ldt2 = new Timestamp(System.currentTimeMillis()).toLocalDateTime();

java.time vs 旧 API 比較

観点旧 (Date/Calendar)新 (java.time)
イミュータブル×
スレッドセーフ×
月の起点0 始まり (Calendar)1 始まり
API 直感性低い高い (流暢な API)
タイムゾーン処理煩雑明示的・型安全
期間表現なしPeriod / Duration

FAQ

Q: SimpleDateFormat はなぜスレッドアンセーフ?
A: 内部状態を持ち、複数スレッドで使うと壊れる。新 API の DateTimeFormatter はスレッドセーフ。

Q: 月初・月末を取りたい
A: LocalDate.now().withDayOfMonth(1) または TemporalAdjusters.firstDayOfMonth() / lastDayOfMonth()

Q: 営業日計算したい
A: 標準 API は祝日を知らない。Holiday カレンダーや独自テーブルが必要。DayOfWeek で土日判定のみなら標準で可能。