Java LocalDate完全ガイド|基本操作から応用例・FAQまで徹底解説

目次

LocalDateとは何か?

Javaにおける日付の取り扱いは、バージョン8以降、大きく進化しました。その中心となるのが「LocalDate」です。LocalDateは「年月日(例:2025-06-26)」だけを表す不変(イミュータブル)なオブジェクトであり、時間やタイムゾーンの概念を持ちません。たとえば、今日の日付や特定の日付を簡潔かつ安全に扱うことができます。

従来の日付クラスとの違い

Java8以前では、java.util.Datejava.util.Calendarといったクラスが主流でした。しかし、これらのクラスにはいくつかの課題がありました。たとえば、ミスしやすい設計(月が0始まりなど)や、スレッドセーフでないこと扱いが直感的でないことなどです。その結果、バグや意図しない動作につながることも少なくありませんでした。

LocalDateはこれらの問題を解消し、次のような特徴を持っています。

  • 年月日だけを明示的に管理(例:2025年6月26日)
  • 不変オブジェクト(値の変更不可。安全な設計)
  • 直感的なメソッド名・設計(例:plusDays(1)で翌日、getMonthValue()で月番号)
  • タイムゾーン非依存(システムやサーバーの設定によらず一貫した動作)

どんな場面で使うべきか?

LocalDateは、「日付だけを明確に扱いたい」「時間は不要」「日付操作を安全・簡単に実装したい」シーンでとても役立ちます。例えば以下のような場面です。

  • 誕生日や記念日など、時間を伴わない日付の記録
  • スケジュールや締切日などの管理
  • 期日計算や残り日数の算出

このように、LocalDateはJavaの現場における「日付操作の新しいスタンダード」と言えるでしょう。次のセクションでは、LocalDateの基本的な使い方や初期化方法について詳しく解説していきます。

LocalDateの基本操作

LocalDateは、直感的かつシンプルなAPIで日付操作を行うことができます。ここでは、よく使われる基本的な機能とその使い方を具体的な例とともに解説します。

現在の日付を取得する

今日の日付を取得するには、LocalDate.now()メソッドを使います。これは、システムの現在日付(タイムゾーン非依存)をそのままLocalDate型で得ることができます。

import java.time.LocalDate;

LocalDate today = LocalDate.now();
System.out.println(today); // 例:2025-06-26

特定の日付を生成する

過去や未来など任意の日付を生成したい場合は、LocalDate.of(int year, int month, int dayOfMonth)メソッドを利用します。これにより「2024年12月31日」など、好きな日付を自由に作成できます。

LocalDate specialDay = LocalDate.of(2024, 12, 31);
System.out.println(specialDay); // 2024-12-31

文字列から日付へ変換する

「2023-03-15」のような日付形式の文字列からLocalDateを生成したい場合は、LocalDate.parse(String text)メソッドが使えます。
標準のISO形式(”YYYY-MM-DD”)であれば、特別な設定なしでそのまま変換できます。

LocalDate parsedDate = LocalDate.parse("2023-03-15");
System.out.println(parsedDate); // 2023-03-15

独自フォーマットの変換(補足)

もし「2023/03/15」のようにスラッシュ区切りや独自のフォーマットで日付を扱う場合は、DateTimeFormatterと組み合わせてparseすることが可能です。

import java.time.format.DateTimeFormatter;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate formattedDate = LocalDate.parse("2023/03/15", formatter);
System.out.println(formattedDate); // 2023-03-15

このように、LocalDateの基本操作はどれも直感的かつシンプルです。現代的なJavaコードでは、日付の初期化や変換に迷うことはほとんどありません。次章では、LocalDateから年・月・日・曜日など各要素を取り出す方法を詳しく解説します。

年月日や曜日の取得

LocalDateは「年月日」という基本情報だけでなく、さまざまな要素を個別に簡単に取り出すことができます。ここでは、よく使われる年、月、日、曜日などの取得方法について解説します。

年・月・日を取得する

LocalDateインスタンスから、それぞれの値を取得するには、専用のメソッドを使います。

LocalDate date = LocalDate.of(2025, 6, 26);

int year = date.getYear();           // 年(例:2025)
int month = date.getMonthValue();    // 月(1~12の数値、例:6)
int day = date.getDayOfMonth();      // 日(1~31の数値、例:26)

System.out.println("年: " + year);
System.out.println("月: " + month);
System.out.println("日: " + day);

月名・曜日名を取得する

月や曜日を「日本語で表示したい」「英語の表記が必要」といった場合にも、LocalDateは柔軟に対応できます。

  • 月の名称(英語表記)
    getMonth()を使うと、Month型(例:JUNE)で取得できます。
import java.time.Month;

Month monthName = date.getMonth(); // JUNE(英語大文字)
System.out.println(monthName);
  • 曜日の名称
    getDayOfWeek()は、DayOfWeek型(例:THURSDAY)を返します。
import java.time.DayOfWeek;

DayOfWeek dayOfWeek = date.getDayOfWeek(); // THURSDAY(英語大文字)
System.out.println(dayOfWeek);

日本語で曜日や月名を表示する

英語表記ではなく日本語で曜日や月名を表示したい場合は、DateTimeFormatterを使うことでカスタマイズ可能です。

import java.time.format.DateTimeFormatter;
import java.util.Locale;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日(E)", Locale.JAPANESE);
String formatted = date.format(formatter); // 2025年06月26日(木)
System.out.println(formatted);

各要素のまとめ

LocalDateは、年・月・日・曜日などを直感的なメソッドで簡単に取得できる点が特徴です。
こうした取り出し方を知っておくと、業務アプリやWebアプリケーションでの日付管理がより柔軟になります。

日付計算(加減算)

日付の加算・減算は、スケジュール管理や期日の計算など、実務のさまざまな場面で頻繁に使われます。LocalDateを使うことで、「1週間後の日付」や「3日前の日付」「2つの日付の差」など、直感的かつ安全に日付計算を行うことができます。

日付を加算する

  • 日数を加える
LocalDate today = LocalDate.of(2025, 6, 26);
LocalDate threeDaysLater = today.plusDays(3); // 3日後
System.out.println(threeDaysLater); // 2025-06-29
  • 月や年を加える
LocalDate nextMonth = today.plusMonths(1); // 1か月後
LocalDate nextYear = today.plusYears(1);   // 1年後
System.out.println(nextMonth); // 2025-07-26
System.out.println(nextYear);  // 2026-06-26

日付を減算する

  • 日数・月・年を減らす場合
LocalDate lastWeek = today.minusWeeks(1); // 1週間前
LocalDate previousDay = today.minusDays(1); // 前日
System.out.println(lastWeek); // 2025-06-19
System.out.println(previousDay); // 2025-06-25

日付同士の差分を計算する

  • 2つの日付の差(日数)を求める
import java.time.temporal.ChronoUnit;

LocalDate start = LocalDate.of(2025, 6, 1);
LocalDate end = LocalDate.of(2025, 6, 26);
long daysBetween = ChronoUnit.DAYS.between(start, end); // 25
System.out.println(daysBetween); // 25
  • 他の単位で差を求める(例:月単位、年単位)
long monthsBetween = ChronoUnit.MONTHS.between(start, end); // 0(同じ月内なので0)
long yearsBetween = ChronoUnit.YEARS.between(start, end);   // 0

まとめ

LocalDateの加算・減算メソッドを活用することで、「1ヶ月後の締切」や「前回のイベントから何日経過したか」など、現場でよくある日付計算が簡単に実装できます。
また、元の日付インスタンスは変更されず、新しいLocalDateインスタンスが返されるため、安全に日付操作を行える点も大きな特徴です。

高度な操作:特定日付の調整

日付操作の現場では、「その月の最終日」や「次の月初」など、単純な加減算だけでは対応しきれないケースも少なくありません。LocalDateは、こうした特定日付の調整にも便利なメソッドやAPIを備えています。

TemporalAdjusterの利用

LocalDateでは、with()メソッドとTemporalAdjuster(調整子)を組み合わせることで、「月末」「月初」「次の特定曜日」などの操作が直感的にできます。標準で用意された調整子はTemporalAdjustersクラスにまとめられています。

月末・月初の日付を取得する

  • 月末の日付を取得する
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

LocalDate date = LocalDate.of(2025, 6, 26);
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(endOfMonth); // 2025-06-30
  • 月初の日付を取得する
LocalDate startOfMonth = date.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(startOfMonth); // 2025-06-01

特定の曜日を取得する

「今月の第2月曜日」や「次の金曜日」など、曜日を基準にした調整も簡単です。

  • 次の金曜日を取得する
import java.time.DayOfWeek;
LocalDate nextFriday = date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
System.out.println(nextFriday); // 2025-06-27(金曜日)
  • 今月の第2月曜日を取得する
LocalDate secondMonday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY));
System.out.println(secondMonday); // 2025-06-09

年始・年末などその他の調整

年初や年末の日付も同様の方法で取得可能です。

LocalDate startOfYear = date.with(TemporalAdjusters.firstDayOfYear());
LocalDate endOfYear = date.with(TemporalAdjusters.lastDayOfYear());
System.out.println(startOfYear); // 2025-01-01
System.out.println(endOfYear);   // 2025-12-31

カスタム調整子も作れる

独自のルールに基づいた日付調整が必要な場合は、TemporalAdjusterインターフェースを実装することで、自由な調整も可能です。

このように、LocalDateとTemporalAdjustersの組み合わせは、複雑な日付計算も直感的かつ柔軟に実現できます。実務で「〇〇の締切」や「特定のイベント日」などをプログラムで扱う際に非常に役立つ機能です。

LocalDateとLocalDateTimeの連携

Javaの日付・時刻API(java.timeパッケージ)では、「日付だけ」を表すLocalDateと、「日付+時刻」を表すLocalDateTimeが明確に分かれています。しかし、実際の開発現場では「日付から時刻付きデータへ変換したい」「逆に時刻情報を切り離して日付だけにしたい」といった場面もよくあります。ここでは、LocalDateとLocalDateTimeを相互に変換する方法について解説します。

LocalDateからLocalDateTimeへの変換

LocalDateに時刻情報を加えてLocalDateTimeへ変換するには、atTime()atStartOfDay()メソッドを使います。

  • 指定した時刻を追加する場合
import java.time.LocalDate;
import java.time.LocalDateTime;

LocalDate date = LocalDate.of(2025, 6, 26);
LocalDateTime dateTime = date.atTime(14, 30, 0); // 2025-06-26 14:30:00
System.out.println(dateTime);
  • その日の0時0分0秒(午前0時)で生成する場合
LocalDateTime startOfDay = date.atStartOfDay(); // 2025-06-26T00:00
System.out.println(startOfDay);

LocalDateTimeからLocalDateへの変換

LocalDateTimeのインスタンスから日付部分だけを抽出したい場合は、toLocalDate()メソッドを使います。

import java.time.LocalDateTime;

LocalDateTime dateTime = LocalDateTime.of(2025, 6, 26, 14, 30);
LocalDate dateOnly = dateTime.toLocalDate(); // 2025-06-26
System.out.println(dateOnly);

LocalTimeとの組み合わせ

日付(LocalDate)と時刻(LocalTime)を組み合わせてLocalDateTimeを生成することもできます。

import java.time.LocalTime;

LocalTime time = LocalTime.of(9, 0);
LocalDateTime combined = date.atTime(time); // 2025-06-26T09:00
System.out.println(combined);

まとめ

  • LocalDateLocalDateTime への変換は atTime()またはatStartOfDay()
  • LocalDateTimeLocalDate への変換は toLocalDate()
  • 日付と時刻の分離・結合は、現実のシステム開発でも頻繁に登場します

LocalDateとLocalDateTimeを柔軟に扱うことで、「日付のみ」「日付+時刻」両方のニーズに対応できるようになります。

例外処理とベストプラクティス

日付の取り扱いは、入力値や計算結果によって思わぬ例外やエラーが発生しがちです。LocalDateを使う場合も、存在しない日付の指定パース時の形式ミスなどで例外が発生することがあります。この章では、LocalDateにおける主な例外と、その安全な扱い方・ベストプラクティスを解説します。

存在しない日付を指定した場合

例えば「2023年2月30日」のように、存在しない日付を生成しようとするとDateTimeExceptionが発生します。

import java.time.LocalDate;

// 例外発生例
LocalDate invalidDate = LocalDate.of(2023, 2, 30); // 実行時に例外発生

このような場合、try-catch構文で例外をキャッチし、適切なエラーハンドリングを行うことが重要です。

try {
    LocalDate invalidDate = LocalDate.of(2023, 2, 30);
} catch (DateTimeException e) {
    System.out.println("存在しない日付が指定されました: " + e.getMessage());
}

文字列パース時の例外

LocalDate.parse()でフォーマットが合わない文字列や不正な日付をパースしようとすると、DateTimeParseExceptionが発生します。

import java.time.format.DateTimeParseException;

try {
    LocalDate date = LocalDate.parse("2023/02/30"); // ISO形式でない&不正日付
} catch (DateTimeParseException e) {
    System.out.println("日付のパースに失敗しました: " + e.getMessage());
}

ベストプラクティス

  • 入力値は事前に検証する
    ユーザーから入力を受ける場合は、事前に「フォーマットチェック」「値の妥当性チェック」を行い、例外が発生しないようにするのがベストです。
  • 例外はcatchしてユーザーに優しいメッセージを
    万が一例外が発生しても、プログラムが落ちるのではなく、ユーザーに分かりやすいエラーメッセージを返すのが理想です。
  • 不変オブジェクトの特性を活かす
    LocalDateは値の変更ができないため、計算結果を元のインスタンスに上書きせず、常に新しいインスタンスとして受け取ることを意識しましょう。

よくある落とし穴

  • 2月29日(うるう年)の扱い
  • 月や日の値の範囲外指定(例:month=13、day=0)
  • 文字列パース時のフォーマット違い

これらは特に初心者がミスしやすいので注意しましょう。

LocalDateの応用ユースケース

LocalDateは単なる日付管理にとどまらず、さまざまな実務シーンや業務システムで活用されています。ここでは、実際の現場で役立つ応用例をいくつか紹介します。

誕生日や年齢の計算

生年月日をもとに「今年で何歳になるか?」を計算するのは、定番のユースケースです。
LocalDateとPeriodを使えば、年齢計算も簡単にできます。

import java.time.LocalDate;
import java.time.Period;

LocalDate birthDay = LocalDate.of(1990, 8, 15);
LocalDate today = LocalDate.now();

Period period = Period.between(birthDay, today);
int age = period.getYears();
System.out.println("年齢: " + age + "歳");

締切日や期日の管理

業務システムやタスク管理で「締切まであと何日?」「支払日を自動計算したい」という場面でもLocalDateは活躍します。

LocalDate deadline = LocalDate.of(2025, 7, 10);
long daysLeft = java.time.temporal.ChronoUnit.DAYS.between(today, deadline);

System.out.println("締切まで残り: " + daysLeft + "日");

スケジュールやカレンダー作成

月ごとのスケジュール表や「毎月第2月曜日に会議」などの要件も、TemporalAdjustersを組み合わせることでシンプルに実装可能です。

import java.time.DayOfWeek;
import java.time.temporal.TemporalAdjusters;

LocalDate secondMonday = LocalDate.of(2025, 7, 1)
    .with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY));
System.out.println("7月の第2月曜日: " + secondMonday);

WebシステムやAPIでの日付入力・バリデーション

WebアプリケーションやAPIのバックエンドで、日付のバリデーションや変換処理にLocalDateがよく使われます。
たとえば「未来日付は受け付けない」「過去10年以内の日付のみ有効」といった判定も容易です。

LocalDate inputDate = LocalDate.parse("2024-12-31");
LocalDate tenYearsAgo = today.minusYears(10);

if (inputDate.isAfter(today)) {
    System.out.println("未来の日付は指定できません");
} else if (inputDate.isBefore(tenYearsAgo)) {
    System.out.println("過去10年以内の日付を指定してください");
} else {
    System.out.println("有効な日付です");
}

新人研修・システム開発現場での採用例

競合記事でもよく取り上げられるように、新人研修やJavaの基礎学習カリキュラムでもLocalDateの活用は定番となっています。
実際のプロジェクトでも「銀行の営業日計算」「在庫の入出庫管理」など、多彩な分野で活用されています。

このように、LocalDateはあらゆるJava現場で“汎用的な日付操作ツール”として使われています。使いこなすことで、シンプルかつ堅牢な日付処理を実現できます。

FAQ(よくある質問)

LocalDateを使い始めたばかりの方や、現場で日付処理に悩む方からよく寄せられる疑問とその回答をまとめました。

Q1. LocalDateとDateの違いは何ですか?

A.
LocalDateはJava 8以降の新しい日付API(java.timeパッケージ)で導入されたクラスで、「年月日」のみを表します。一方、java.util.Dateは古いAPIで、「年月日+時刻」を含み、内部的にミリ秒単位で管理されています。
LocalDateはイミュータブルで直感的、かつスレッドセーフな設計が特徴です。これからのJava開発では、原則としてLocalDateの利用が推奨されます。

Q2. LocalDateでタイムゾーンは扱えますか?

A.
LocalDate自体はタイムゾーンの情報を持ちません。
タイムゾーンを考慮したい場合は、ZonedDateTimeOffsetDateTimeを利用してください。
用途に応じてLocalDateで日付管理→必要に応じてZonedDateTimeへ変換、という流れが一般的です。

Q3. LocalDateTimeとの違いは何ですか?

A.
LocalDateは「年月日」だけを表し、「時刻」の概念はありません。
LocalDateTimeは「年月日+時刻(例:2025-06-26 14:00)」を表します。
例えば、「締切日だけ」を管理したいならLocalDate、
「イベント開始時刻」まで細かく管理したいならLocalDateTimeを選択しましょう。

Q4. 文字列からLocalDateへ変換する際、独自のフォーマットも対応できますか?

A.
はい、DateTimeFormatterを使うことで、ISO形式以外の独自日付フォーマットにも対応可能です。

import java.time.format.DateTimeFormatter;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate date = LocalDate.parse("2025/06/26", formatter);

Q5. 無効な日付や間違ったフォーマットでエラーが出る場合、どうすれば良いですか?

A.
日付が不正(例:2023-02-30)だったり、フォーマットが合っていない場合は例外(DateTimeParseExceptionやDateTimeException)が発生します。
try-catch構文で例外をキャッチし、ユーザーにわかりやすいメッセージを表示したり、事前にフォーマットチェック・日付妥当性チェックを行うことで安全に処理しましょう。

Q6. LocalDate同士の比較はできますか?

A.
はい、isAfter()isBefore()isEqual()などのメソッドで簡単に比較できます。

LocalDate date1 = LocalDate.of(2025, 6, 26);
LocalDate date2 = LocalDate.of(2025, 7, 1);

if (date1.isBefore(date2)) {
    System.out.println("date1はdate2より前の日付です");
}

FAQで紹介した内容は、現場で頻繁に出てくる疑問・トラブルの“即答”になるものばかりです。疑問点は都度公式リファレンスやこの記事を活用してください。

まとめ

本記事では、「java localdate」をテーマに、LocalDateの基礎から応用までを徹底解説してきました。
ここで、重要なポイントをもう一度振り返ります。

  • LocalDateとは
    Java 8以降で導入された「年月日だけ」を扱う不変オブジェクト。古いDate/Calendarクラスの弱点を解消し、直感的かつ安全に日付を操作できます。
  • 基本的な使い方
    現在日付の取得、特定日付の生成、文字列からの変換など、シンプルなメソッドで簡単に操作できます。
  • 年月日・曜日の取得
    年、月、日、曜日など、必要な要素を明確に取り出せます。日本語でのフォーマットや表示も自在です。
  • 日付の加減算と差分計算
    plusDays/minusMonthsなどを使い、期日計算や締切管理が直感的に実装できます。
  • 特定日付の調整
    TemporalAdjustersを使えば、「月末」「次の金曜日」など、実務で役立つ複雑な日付調整も簡単です。
  • LocalDateTimeやLocalTimeとの連携
    日付だけでなく、時刻情報との相互変換も柔軟に行えます。
  • 例外処理と安全な使い方
    不正な日付やフォーマットミスには例外が発生します。try-catchや入力バリデーションを組み合わせ、堅牢なシステムを目指しましょう。
  • 業務での応用・FAQ
    年齢計算、締切管理、カレンダー生成など、現実の開発現場でも幅広く活用されています。FAQでよくある疑問もカバーしました。

今後のステップ

LocalDateをマスターすれば、日付の扱いで困ることはほとんどなくなります。
さらに発展的な日付・時刻管理(タイムゾーン、期間計算、フォーマット変換など)に挑戦したい方は、ZonedDateTimePeriodDateTimeFormatterといったAPIもぜひ学んでみてください。

LocalDateの知識を武器に、現場のJava開発をもっと効率的・スマートに進めていきましょう。