Javaで日付と時間を操作する方法:Date, Calendar, LocalDateの使い方

Java_icon Java
この記事は約17分で読めます。

この記事は、以下の方を対象に書いています。

  • 日付や時間の扱い方を知りたい
  • Date, Calendar, LocalDateの違いを知りたい

日付や時間を扱うクラス

Javaには日付や時間を扱うクラスが様々存在します。

今回は、その中でも代表的な3つのクラスを紹介します。

既に知識がある方で、すぐに扱い方を知りたい方は、

本記事の後半でサンプルコードの紹介をしていますので、目次から飛んでください。

Date

Dateクラスは、Javaの初期から存在している日付や時間を扱うクラスです。

しかし、現在では問題が見つかり、改良された新しいクラスが登場したため、

なかなか見かけなくなりました。

ですが、古いシステムではJavaのバージョンも古く、

Dateクラスを扱わないといけない場合もあります。

Date型の扱い方は、以下の通りです。

import java.util.Date;

public class Main {
	public static void main(String[] args) {
		Date date = new Date();
		System.out.println(date); // Mon Aug 26 16:11:11 JST 2024
	}
}

Calendar

Calendarクラスは、Dateクラスの問題を解決する目的で設計されたクラスになります。

日時の操作やタイムゾーンのサポートも強化されています。

しかし、Calendarクラスも扱いづらさから、

現在ではjava.timeパッケージの使用が推奨されています。

java.timeパッケージは、Java8から導入されたため、

これ以前のバージョンを使用している環境では、使えません。

ですので、今回はCalendarクラスの扱い方や特徴、問題点についても解説します。

概要

Calendarクラスは、Java1.1で導入され、

抽象クラスで日時の計算や操作、タイムゾーンの管理などの機能が提供されています。

現在の日時を取得するには、以下のように記述します。

import java.util.Calendar;

public class Main {
	public static void main(String[] args) {
		Calendar calendar = Calendar.getInstance();
		System.out.println(calendar.getTime()); // Mon Aug 26 16:32:12 JST 2024
	}
}

特徴

Calendarクラスの特徴は、大きく3つあります。

まず1つ目が、柔軟に日時操作ができる点です。

setterやgetterを使って簡単に日時の取得や設定をすることが可能です。

ただし、月のデータは0から始まるため、取得後に+1をする必要があります。

これが、扱いづらいと言われる原因の1つでもあります。

public class Main {
	public static void main(String[] args) {
		Calendar calendar = Calendar.getInstance();
		
		// 日時の取得
		System.out.println(calendar.get(Calendar.YEAR)); // 2024
		System.out.println(calendar.get(Calendar.MONTH) + 1); // 8
		System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 26
		
		// 日時の設定
		calendar.set(Calendar.YEAR, 1222);
		calendar.set(Calendar.MONTH, 11);
		calendar.set(Calendar.DATE, 20);
		
		System.out.println(calendar.get(Calendar.YEAR)); // 1222
		System.out.println(calendar.get(Calendar.MONTH) + 1); // 12
		System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 20
	}
}

2つ目の特徴は、日時の加算や減算が容易にできる点です。

今日から1週間後や3時間前などの日時を容易に取得することができます。

import java.util.Calendar;

public class Main {
	public static void main(String[] args) {
		Calendar calendar = Calendar.getInstance();
		
		// 10年後
		calendar.add(Calendar.YEAR, 10);
		System.out.println(calendar.get(Calendar.YEAR)); // 2034
		
		// 10年前
		calendar.add(Calendar.YEAR, -10);
		System.out.println(calendar.get(Calendar.YEAR)); // 2014
	}
}

問題点

ここまで見ると、便利そうですが、実際に使ってみると不便なことがあります。

まず1つ目は、月の始まりが0になっている点です。

気をつけていれば、問題はないのですが、意外と忘れやすいの厄介です。

2つ目は、スレッドセーフではない点です。

マルチスレッドの環境下では思わぬバグを生む可能性があるので気をつけてください。

他にもありますが、上記の2つが理由でLocalhostクラスを使うのが安全です。

ですが、Javaの古いバージョンを使わなければいけない状況の時もありますので、

CalendarクラスやDateクラスについて知識を入れておくことはお勧めします。

LocalDate

LocalDateクラスは、今回紹介した日付や時間を扱うクラスの中で、

一番使い勝手の良いクラスになります。

余程の事情がない限り、LocalDateクラスを選択することをお勧めします。

基本的な使い方は以下の通りです。

import java.time.LocalDate;

public class Main {
	public static void main(String[] args) {
		LocalDate localDate = LocalDate.now();
		System.out.println(localDate); // 2024-08-27
	}
}

概要

LocalDateクラスは、Java8で導入されたjava.timeパッケージに属しているクラスです。

Calendarクラスの扱いづらさ等の問題を解決しており、

java.timeパッケージの使用が推奨されています。

java.timeパッケージには、LocalDateクラスの他にも、

ZonedTimeDateクラスという便利なクラスもあります。

特徴

LocalDateクラスの特徴は、大きく分けて3つあります。

1つ目は、DateクラスやCalendarクラスと違い、不変的でありスレッドセーフに設計されています。

そのため、マルチスレッド環境下でも安全に動作します。

2つ目は、直感的で読みやすいAPI設計のため、日付操作が比較的簡単に行えます。

例えば、現在の日付を取得する場合も以下の通り簡単です。

LocalDate localDate = LocalDate.now();

3つ目は、タイムゾーンに影響を受けない点です。

タイムゾーンは意外と厄介ですが、LocalDateクラスはシンプルに日付のみを扱います。

問題点

ここまで読んでいただいた方は、「LocalDateクラスを使えばいいじゃん」と思うかもしれません。

ですが、便利すぎるLocalDateクラスにも問題点はいくつか存在します。

まず1つ目は、LocalDateクラスは日付のみを扱うクラスですので、時間情報を扱えません。

そのため、時間情報まで扱いたい場合は、LocalDateTimeクラスを使用します。

時間情報のみ扱いたい場合は、LocalTimeクラスを使用します。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class Main {
	public static void main(String[] args) {
		// LocalDateクラス
		LocalDate localDate = LocalDate.now();
		System.out.println(localDate); // 2024-08-28
		
		// LocalDateTimeクラス
		LocalDateTime localDateTime = LocalDateTime.now();
		System.out.println(localDateTime); // 2024-08-28T10:32:14.797707
		
		// LocalTimeクラス
		LocalTime localTime = LocalTime.now();
		System.out.println(localTime); // 12:11:09.177761
		
		System.out.println(localDate + " " + localTime); // 2024-08-28 12:13:29.922641
	}
}

2つ目は、タイムゾーンを考慮しなくて良くなった代わりに、

タイムゾーンを使いたい場合に使えないという問題です。

タイムゾーンの情報を使用したい場合は、

以下のように ZonedDateTimeクラスやOffsetDateTimeクラスを使用します。

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
	public static void main(String[] args) {
		// ZonedDateTimeクラス(デフォルトのタイムゾーン)
		ZonedDateTime zonedDateTime = ZonedDateTime.now();
		System.out.println(zonedDateTime); // 2024-08-28T12:39:41.312858+09:00[Asia/Tokyo]
		
		// ZonedDateTimeクラス(NewYorkのタイムゾーン)
		ZonedDateTime newYorkTime = zonedDateTime.withZoneSameInstant(ZoneId.of("America/New_York"));
        System.out.println(newYorkTime); // 2024-08-27T23:41:21.774902-04:00[America/New_York]
        
        // OffsetDateTimeクラス(デフォルトのオフセット)
        OffsetDateTime offsetDateTime = OffsetDateTime.now();
        System.out.println(offsetDateTime); // 2024-08-28T12:43:06.022404+09:00
        
        // OffsetDateTimeクラス(UTC+02:00)
        OffsetDateTime offsetTime = offsetDateTime.withOffsetSameInstant(ZoneOffset.of("+02:00"));
        System.out.println(offsetTime); // 2024-08-28T05:44:45.313110+02:00
	}
}

各クラスの使い分け

ここまで紹介してきた各クラスの、使い分けについて紹介します。

※あくまでも個人の意見にはなりますので、ご参考程度に。。。

日付や時間を扱いたい場合、基本的にはLocalDate(LocalDateTime、LocalTime)を

使うべきだと考えています。

理由としては、マルチスレッド環境のプログラムが近年増えてきていることと、

直感的にわかりやすいAPI設計のため、可読性に優れていることが主な理由です。

LocalDateを使わない場合は、Java8以下のバージョンだったりする時です。

ただし、DateクラスやCalendarクラスの知識もある程度ないと、

古いシステムの改修時に苦労するので、

せっかく学ぶなら3つとも知っておいたほうが良いと思います。

サンプルコード

ここでは、日付や時間の操作をするための実践的なサンプルコードをいくつか紹介します。

フォーマットを指定したい

日付のフォーマット(形式)を直接指定したい場合があると思います。

ここでは、様々な形に加工してみたいと思います。

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

public class Main {
	public static void main(String[] args) {
		// ① 日付を取得
		LocalDate localDate = LocalDate.of(2024, 6, 1);
		// ② DateTimeFormatterクラスを使用してフォーマットを定義
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
		// ③ ①を②の形式に変換する
		String formattedDate = localDate.format(formatter);
		// ④ コンソール表示
		System.out.println(formattedDate); // 2024/08/28
		
		DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
		String formattedDate1 = localDate.format(formatter1);
		System.out.println(formattedDate1); // 2024月08日28
		
		DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yy年M月d日");
		String formattedDate2 = localDate.format(formatter2);
		System.out.println(formattedDate2); // 24年6月1日
		
		LocalDateTime localDateTime = LocalDateTime.now();
		DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
		String formattedDate3 = localDateTime.format(formatter3);
		System.out.println(formattedDate3); // 2024年08月28日 15:24:59

		DateTimeFormatter formatter4 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時");
		String formattedDate4 = localDateTime.format(formatter4);
		System.out.println(formattedDate4); // 2024年08月28日 15時
		
		DateTimeFormatter formatter5 = DateTimeFormatter.ofPattern("MM月dd日 HH時mm分 ジム予約");
		String formattedDate5 = localDateTime.format(formatter5);
		System.out.println(formattedDate5); // 08月28日 15時28分 ジム予約
	}
}

1週間前(後)の日付を取得したい

次は、現在日付から1週間後や1週間前などの日付を取得したい時があると思います。

このような状況は意外とあるのでサンプルコードを紹介します。

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

public class Main {
	public static void main(String[] args) {
		// 日付を取得
		LocalDate localDate = LocalDate.of(2024, 6, 1);
		// 1週間後の日付を取得
		LocalDate localDatePlus7 = localDate.plusDays(7);
		// コンソール表示
		System.out.println(localDatePlus7); // 2024-06-08
		
		// 1週間前の日付を取得
		LocalDate localDateMinus7 = localDate.plusDays(-7);
		System.out.println(localDateMinus7); // 2024-05-25
		
		// 現在時刻から3時間後の時刻
		LocalDateTime localDateTime = LocalDateTime.of(2024, 6, 7, 4, 0, 0);
		LocalDateTime localDateTimePlus3 = localDateTime.plusHours(3);
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH時mm分ss秒");
		String formattedLocalDateTimePlus3 = localDateTimePlus3.format(formatter);
		System.out.println(formattedLocalDateTimePlus3); // 2024-06-07 07時00分00秒
		
		// 現在時刻から2時間前の時刻
		LocalDateTime localDateTimeMinus2 = localDateTime.minusHours(2);
		String formattedLocalDateTimeMinus2 = localDateTimeMinus2.format(formatter);
		System.out.println(formattedLocalDateTimeMinus2); // 2024-06-07 02時00分00秒
	}
}

指定日が現在日付より前か後か知りたい

次は、指定された日付と現在日付を比較して、過去なのか未来なのか知りたい場合に

使えるサンプルコードを紹介します。

import java.time.LocalDate;

public class Main {
	public static void main(String[] args) {
		// 指定日を設定(2024-06-01)
		LocalDate targetDate = LocalDate.of(2024, 6, 1);
		// 現在日付を取得(2024-08-28)
		LocalDate nowDate = LocalDate.now();
		
		// isAfterメソッドで判定
		if (targetDate.isAfter(nowDate)) {
			System.out.println("指定日は未来です");
		} else {
			System.out.println("指定日は過去です");
		}
	}
}

最後に

ここまで読んでいただきありがとうございます。

今回は、Javaで日付や時間を操作する方法を紹介しました。

Javaは歴史のある言語ですので、便利なクラスやメソッドがたくさんあります。

今回紹介したもの以外にも便利なクラスやメソッドはたくさんあるので、

サンプルコードを改造して、いろいろ試していただきたいと思います。

コメント

タイトルとURLをコピーしました