2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【圧倒的早見表】Javaの日付・時刻はもう怖くない!3世代クラスの使い分け速習

Posted at

はじめに:なぜJavaの日付はこんなに複雑なのか?

はじめまして、学生エンジニアの@huyunokiです。

Javaの学習を始めた皆さんは日付や時刻を扱おうとしてDateCalendarLocalDateTimeと似たようなクラスがたくさん出てきて混乱しませんでしたか?

「とりあえず動けばいい」と適当に選ぶと実務で思わぬバグ(特に時差や月またぎ)の原因になります。

この記事は「なぜJavaには3つもクラスがあるのか?」という疑問を解決し「どの場面でどれを使えばいいか」を一瞬で判断できる最強の早見表を目的としています。

この記事を読めば、あなたはJavaのモダンな日付APIを使いこなし将来のバグを未然に防げるようになります。

結論:まずはこれだけ覚えよう!3クラスの立ち位置

まず結論から。現在のJava開発では、原則としてJava 8以降で導入された新しいAPI」を使うべきです。

代表クラス 主な用途 なぜ新しいAPIを使うべきか
LocalDate, LocalDateTime 原則これを使う! 日付計算、表示、ロジック処理など、ほぼ全て。 不変でスレッドセーフ。直感的でバグが少ない。
Calendar 過去の資産との連携が必要な時のみ。 可変でスレッドセーフではない。古いコードの修正時などに限定。
Date タイムスタンプ(ミリ秒)としてデータを受け渡しする時のみ。 可変で使いにくい。一部では非推奨という声も。

圧倒的早見表!3世代クラスの「使い分け」と「基本関数」

ここからは、各クラスの具体的な特徴と使い方を見ていきましょう。

1. モダンAPI (java.time.* パッケージ)

Java 8で導入された「不変(Immutable)」なクラス群です。一度値をセットすると変更できず、安全性が高いのが特徴です。

クラス名 保持する情報 開発でよく使う関数(例) 使い分けのポイント
LocalDate 日付のみ (年/月/日) now(): 今日の日付を取得
plusDays(int): 日付を加算
getDayOfWeek(): 曜日を取得
「何時何分」が不要な時(例:誕生日、締め切り日)。
LocalTime 時刻のみ (時/分/秒/ナノ秒) now(): 現在時刻を取得
of(h, m): 特定時刻を生成
isBefore(LocalTime): 時刻の比較
「今日の日付」が不要な時(例:営業開始時間)。
LocalDateTime 日付 + 時刻 now(): 現在の日付と時刻を取得
format(DateTimeFormatter): 任意の形式で表示
「いつの何時何分」が必要で、 タイムゾーンが関係ない時(これはタイムゾーンを保持しないため、実際の瞬間を表せないからである)
ZonedDateTime 日付 + 時刻 + タイムゾーン now(ZoneId): ゾーンを指定して取得
withZoneSameInstant(): タイムゾーン変換
国際的なシステムや、夏時間を扱う時(実務で非常に重要)。

処理例 (LocalDateTime)

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// 例として 2025年11月17日 15:30:00 の実行結果を想定

public class ModernDateTimeExample {
    public static void main(String[] args) {
        // 1. 現在の日時を取得
        LocalDateTime now = LocalDateTime.now(); 
        System.out.println("現在日時: " + now); 
        // -> 現在日時: 2025-11-17T15:30:00.123
        
        // 2. 5日後を計算(不変なので、新しいインスタンスが生成される)
        LocalDateTime nextWeek = now.plusDays(5);
        System.out.println("5日後: " + nextWeek); 
        // -> 5日後: 2025-11-22T15:30:00.123
        
        // 3. 5日後の曜日を取得
        DayOfWeek day = nextWeek.getDayOfWeek();
        System.out.println("5日後の曜日: " + day); 
        // -> 5日後の曜日: SATURDAY
        
        // 4. フォーマットを指定して表示
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        System.out.println("整形後: " + nextWeek.format(formatter)); 
        // -> 整形後: 2025/11/22 15:30:00
    }
}

2. レガシーAPI (Calendar / Date)

第1世代の欠点を補うために登場しましたが、可変であることや Calendar月を0から数える(0月=1月)など直感的でない仕様がありあまり推奨されない。

クラス名 欠点 実務でよく使う関数(例) 使い分けのポイント
Calendar 可変(一度作ったオブジェクトが変更可能)
スレッドセーフではない
getInstance(): 現在時刻で取得
add(フィールド, 量): 日付を加算/減算
古いフレームワーク外部APIがこの型を求めてくる場合のみ。
Date 可変(非推奨メソッド多数)
保持するのはミリ秒のみ
getTime(): 1970/1/1からのミリ秒を取得 データベースや外部APIとのタイムスタンプ(数値)の受け渡しに限定。

処理例(Calendar)

import java.util.Calendar;
import java.util.Date;
// 例として 2025年11月17日 15:30:00 の実行結果を想定

public class LegacyDateTimeExample {
    public static void main(String[] args) {
        // 1. Date型はミリ秒で表現される
        Date now = new Date();
        System.out.println("現在日時(Date): " + now); 
        // -> 現在日時(Date): Mon Nov 17 15:30:00 JST 2025 (※表示は環境依存)

        // 2. Calendarの取得
        Calendar cal = Calendar.getInstance();
        System.out.println("現在日時(Calendar): " + cal.getTime()); 
        // -> 現在日時(Calendar): Mon Nov 17 15:30:00 JST 2025
        
        // 3. 5日後を計算
        cal.add(Calendar.DAY_OF_MONTH, 5); // calオブジェクト自身が変更される(可変)
        System.out.println("5日後(Calendar): " + cal.getTime()); 
        // -> 5日後(Calendar): Sat Nov 22 15:30:00 JST 2025
        
        // 4. 月を取得 (※0から始まることに注意!11月は10となる)
        int month = cal.get(Calendar.MONTH);
        System.out.println("5日後の月(0から始まる): " + month);
        // -> 5日後の月(0から始まる): 10 
    }
}

実務で絶対避けるべき!日付処理の地雷

Java初心者が実務に入る前に知っておくべき、日付処理の大きな落とし穴を2つ伝えます。

1. 「==」で日付オブジェクトを比較してはいけない

文字列と同じで DateLocalDateTimeなどのオブジェクトを比較する際は ==(参照の比較)ではなく、必ず equals() メソッド(値の比較)を使いましょう。

悪い例 良い例
if (date1 == date2) if (date1.equals(date2))

2. Date型をそのまま表示・計算に使ってはいけない

Date型は、内部的にミリ秒という数値を持っているだけで、System.out.println(date)で表示される文字列は実行環境のタイムゾーンに依存します。計算も難しいため、Date型を受け取ったらすぐにLocalDateTimeなどに変換してから使いましょう。

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

// 【推奨】変換してから使う
Date legacyDate = new Date(); // Date型で受け取った
LocalDateTime modernDate = legacyDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); 

// これで安全に計算や表示ができる
System.out.println(modernDate.plusMonths(1)); 
// -> 2025-12-17T15:30:00.123 (安全に翌月を計算できる)

まとめ:今日からあなたはモダンJava使い!

Javaの日付・時刻クラスの使い分けは現代的な開発においてコードの安全性(バグの少なさ)に直結します。

  • 原則: java.time パッケージを使う!
  • 理由: 不変だから、意図しない書き換えのバグを防げる!
  • レガシー: DateCalendarは、古いコードや外部API連携時のみ使うと割り切る!

この早見表が、皆さんのJava学習を加速させるカンニングペーパーになれば嬉しいです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?