Javaを使用したシステム開発において、日付や時刻の操作は避けては通れない非常に重要な要素です。

ログの出力、DBへの登録日時、ユーザーへの通知期限など、あらゆる場面で「今日の日付」を取得し、適切な形式に加工する処理が必要となります。

以前のJavaでは java.util.Datejava.util.Calendar クラスが使われてきましたが、現在のJava開発においては、Java 8から導入された Date-Time API を使用するのが標準となっています。

本記事では、初心者から実務者まで役立つ、Javaで今日の日付をスマートに取得・操作する方法を詳しく解説します。

Javaの日時処理における主要クラスの概要

Java 8で導入された java.time パッケージ、通称「Date-Time API」は、それ以前のクラスが抱えていた多くの課題を解決するために設計されました。

かつての Date クラスなどは、スレッドセーフではない(複数の処理から同時に触ると不具合が起きやすい)ことや、月が0から始まる(1月が0)といった直感的でない設計が問題視されていました。

現代のJava開発で「今日の日付」や「現在の時刻」を扱う際に主に利用されるのは、以下の4つのクラスです。

LocalDate

日付のみ(年・月・日)を扱うクラス。

時刻やタイムゾーンの情報は持ちません。

LocalTime

時刻のみ(時・分・秒・ナノ秒)を扱うクラス。

LocalDateTime

日付と時刻の両方を扱うクラス。

タイムゾーンの情報は持ちません。

ZonedDateTime

日付・時刻に加えて、タイムゾーン(東京、ニューヨークなど)の情報を扱うクラス。

これらのクラスはすべて 不変(イミュータブル) であり、一度生成されたインスタンスの内容が書き換わることはありません。

これにより、マルチスレッド環境下でも安全に利用できるという大きなメリットがあります。

今日(現在)の日付を取得する基本:LocalDate

日付のみが必要な場合、最も頻繁に利用されるのが LocalDate クラスです。

例えば、「今日が何日か」を知りたいだけの場合や、誕生日の計算、有効期限のチェックなどに適しています。

今日の日付を取得するには、LocalDate.now() メソッドを使用します。

このメソッドを呼び出すだけで、実行環境のシステム・クロックに基づいた現在の日付が取得できます。

LocalDateの使用例

以下のプログラムは、今日の日付を取得して標準出力に表示する最もシンプルな例です。

Java
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        // 今日の日付を取得
        LocalDate today = LocalDate.now();
        
        // 結果を出力
        System.out.println("今日の日付: " + today);
        
        // 個別の要素を取得することも可能
        int year = today.getYear();
        int month = today.getMonthValue();
        int day = today.getDayOfMonth();
        
        System.out.println(year + "年" + month + "月" + day + "日");
    }
}
実行結果
今日の日付: 2024-05-20
2024年5月20日

デフォルトの出力形式は ISO-8601形式(yyyy-MM-dd) となります。

月を1から12の数値で直感的に扱える点が、旧APIとの大きな違いです。

特定の日時を取得する:LocalDateTimeとZonedDateTime

日付だけでなく、現在の「時間」まで含めて取得したい場合は LocalDateTime を、さらに「どこの地域の時間か」というタイムゾーン情報まで厳密に管理したい場合は ZonedDateTime を使用します。

LocalDateTimeで現在日時を取得

システムログの記録など、秒単位の精度が必要な場合に適しています。

Java
import java.time.LocalDateTime;

public class DateTimeExample {
    public static void main(String[] args) {
        // 現在の日時を取得
        LocalDateTime now = LocalDateTime.now();
        System.out.println("現在の日時: " + now);
    }
}
実行結果
現在の日時: 2024-05-20T14:30:15.123456789

ZonedDateTimeでタイムゾーンを考慮

グローバルなアプリケーションを展開する場合、サーバーがどこにあっても「日本時間」で取得したいといったニーズがあります。

その場合は ZoneId を指定します。

Java
import java.time.ZonedDateTime;
import java.time.ZoneId;

public class ZonedExample {
    public static void main(String[] args) {
        // 日本の標準時で現在日時を取得
        ZonedDateTime jstNow = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
        System.out.println("日本時間: " + jstNow);
        
        // ニューヨークの標準時を取得
        ZonedDateTime nyNow = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("ニューヨーク時間: " + nyNow);
    }
}
実行結果
日本時間: 2024-05-20T14:30:15.123456789+09:00[Asia/Tokyo]
ニューヨーク時間: 2024-05-20T01:30:15.123456789-04:00[America/New_York]

日付のフォーマットを変更する(DateTimeFormatter)

デフォルトの yyyy-MM-dd 形式ではなく、「2024/05/20」や「2024年05月20日 14時30分」といった任意の形式で出力したい場合は、DateTimeFormatter クラスを使用します。

指定したパターンでフォーマットする

DateTimeFormatter.ofPattern() メソッドにパターンの文字列を渡すことで、自由な書式を定義できます。

Java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FormatExample {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        
        // フォーマットパターンの定義
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        
        // 日時を文字列に変換(書式化)
        String formattedDate = now.format(formatter);
        
        System.out.println("フォーマット後: " + formattedDate);
    }
}
実行結果
フォーマット後: 2024/05/20 14:30:15

よく使われるフォーマットパターン記号

日付フォーマットを指定する際に使用する代表的な記号は以下の通りです。

大文字と小文字で意味が異なるため注意してください。

記号意味記述例
y2024, 24
M月(数値)05, 5
d01, 20
E曜日月, Monday
H時(0-23時)09, 21
m05, 59
s08, 30
注意点

月を表すのは大文字の M であり、小文字の m は「分」を表します。

また、24時間表記には大文字の H を使用します。

文字列から日付オブジェクトへの変換(パース)

逆に、「2024/05/20」といった文字列を LocalDate オブジェクトに変換したい場合も DateTimeFormatter を使用します。

Java
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class ParseExample {
    public static void main(String[] args) {
        String dateStr = "2024/05/20";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        
        // 文字列をLocalDateに変換
        LocalDate parsedDate = LocalDate.parse(dateStr, formatter);
        
        System.out.println("パースされた日付: " + parsedDate);
    }
}

日付の計算と操作

Java 8以降のAPIでは、日付の加算や減算も非常に直感的に記述できます。

これらのメソッドは元のオブジェクトを変更せず、計算結果を新しいオブジェクトとして返す ことに注意しましょう。

加算と減算(plus/minus)

「1週間後」や「1ヶ月前」の日付を求めるのは簡単です。

Java
import java.time.LocalDate;

public class CalculationExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        
        // 10日後を計算
        LocalDate after10Days = today.plusDays(10);
        
        // 2ヶ月前を計算
        LocalDate before2Months = today.minusMonths(2);
        
        // 1年後を計算
        LocalDate nextYear = today.plusYears(1);

        System.out.println("今日: " + today);
        System.out.println("10日後: " + after10Days);
        System.out.println("2ヶ月前: " + before2Months);
        System.out.println("1年後: " + nextYear);
    }
}

日付の比較(isBefore / isAfter)

2つの日付の前後関係を判定する場合、比較演算子(<>)の代わりに関数を使用します。

Java
import java.time.LocalDate;

public class CompareExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        LocalDate deadline = LocalDate.of(2024, 12, 31);
        
        // 今日が締め切りより前かどうか
        if (today.isBefore(deadline)) {
            System.out.println("まだ期限内です。");
        } else if (today.isAfter(deadline)) {
            System.out.println("期限を過ぎています。");
        } else if (today.isEqual(deadline)) {
            System.out.println("今日が締め切り当日です。");
        }
    }
}

応用編:和暦やロケールの扱い

日本の業務システムでは「令和」などの和暦で日付を扱いたい場面もあります。

Javaでは JapaneseDate クラスを使用することで、簡単に和暦変換が可能です。

和暦(JapaneseDate)の使用

Java
import java.time.LocalDate;
import java.time.chrono.JapaneseDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class JapaneseDateExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        
        // 西暦から和暦に変換
        JapaneseDate jDate = JapaneseDate.from(today);
        
        // 和暦用のフォーマッタ(Locale.JAPANが必要)
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("Gy年MM月dd日")
                                        .withLocale(Locale.JAPAN);
        
        System.out.println("和暦表示: " + jDate.format(formatter));
    }
}
実行結果
和暦表示: 令和6年05月20日

G は元号(令和、平成など)を表すパターン文字です。

和暦を扱う場合は、Locale.JAPAN を明示的に指定することが推奨されます。

【注意点】レガシーなDate/Calendarクラスとの相互変換

古いライブラリや既存のシステムと連携する場合、どうしても java.util.Date 型を新しい LocalDate に変換しなければならない(あるいはその逆)ケースがあります。

java.util.DateからLocalDateへの変換

Instant クラスを経由するのが一般的な方法です。

Java
import java.util.Date;
import java.time.LocalDate;
import java.time.ZoneId;

public class LegacyConversion {
    public static void main(String[] args) {
        // 旧来のDateオブジェクト
        Date oldDate = new Date();
        
        // Date -> Instant -> ZonedDateTime -> LocalDate
        LocalDate newDate = oldDate.toInstant()
                                   .atZone(ZoneId.systemDefault())
                                   .toLocalDate();
        
        System.out.println("変換後の日付: " + newDate);
    }
}

このように、新旧のAPIを仲介させることは可能ですが、変換の過程でタイムゾーンが考慮される必要があるため、コードがやや複雑になります。

新規に開発する箇所では、可能な限り java.time パッケージに統一 し、境界部分でのみ変換を行うように設計しましょう。

まとめ

Javaで今日の日付を取得・操作する方法について解説しました。

現代のJava開発においては、java.time パッケージ(Date-Time API) の利用が必須と言えます。

本記事の要点を振り返ります。

  • 日付のみを取得したい場合は LocalDate.now() を使用する。
  • 日付と時刻が必要な場合は LocalDateTime.now() を使用する。
  • 表示形式を変更したい場合は DateTimeFormatter でパターン(yyyy/MM/ddなど)を指定する。
  • 日付の計算(1日後、1ヶ月前など)は plusDaysminusMonths などのメソッドで直感的に行える。
  • 以前の Date クラスとは異なり、オブジェクトは不変(イミュータブル)であるため安全である。

Javaの日時操作は、基本さえ押さえれば非常に強力で柔軟です。

特にフォーマットの指定や日付の計算は、多くのビジネスロジックの根幹を支える技術ですので、本記事を参考にしっかりとマスターしていきましょう。