java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

うるう年の判定をCalendarクラス・Time APIを使って実装

投稿日:

最終更新日:2019年06月08日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

4桁の自然数を年として与えらた時、うるう年であるか判定するという方法をJavaに用意されているAPIを使って実装してみました。以下の2つのパターンを作ってみました。

  1. Calendarクラスを利用する
  2. Time APIを利用する

Time APIはJava 8から新たに用意されたAPIです。

Calendarクラスで判定

最初にCalendarクラスを使って、うるう年を判定する方法を載せます。基本的な説明から書くので、面倒な場合はソースコードだけ見れば分かると思います。

Calendarクラスを使う場合、インスタンスを取得するという方式になっています。Calendarクラスには、getInstance()というstaticメソッドが用意されています。このメソッドはCalendarクラスのインスタンスを返却します。インスタンスを取得した後は、set()メソッドを呼び出して、日付を設定します。今回使うのはset(int year, int month, int date)です。

例えば、int型変数yearに4桁自然するが格納されているとします。[year]年2月1日のCalendarオブジェクトは以下のように作ります。

Calendarオブジェクトに2月を設定

		// インスタンス取得
		Calendar calendar = Calendar.getInstance();
		// 日付を設定
		calendar.set(year, Calendar.FEBRUARY, 1);

CalendarクラスにはgetActualMaximum(int field)というメソッドが用意されています。引数にはカレンダ・フィールドと呼ばれる値を指定します。Calendar.DATEという定数がこのメソッドのためのフィールド値で、月の日を示します。getActualMaximum(Calendar.DATE)と記述すれば、設定された月が何日あるかが返却されます。29日あれば、うるう年であると判定できます。

うるう年判定のためのメソッドは、例えば、以下のように実装出来ます。

Calendarクラスで判定

	public static boolean judge(int year) {
		// インスタンス取得
		Calendar calendar = Calendar.getInstance();
		// 日付を設定
		calendar.set(year, Calendar.FEBRUARY, 1);
		// 日数を取得
		int numberOfdays = calendar.getActualMaximum(Calendar.DATE);
		// 日数が29日の場合、trueを返却
		return numberOfdays == 29;
	}

以下のような使い方になります。

	public static void main(String[] args) {

		int year = 2016;
		if (judge(year)) {
			System.out.println(year + ": うるう年です。");
		} else {
			System.out.println(year + ": うるう年ではありません。");
		}

		year = 2017;
		if (judge(year)) {
			System.out.println(year + ": うるう年です。");
		} else {
			System.out.println(year + ": うるう年ではありません。");
		}

結果

2016: うるう年です。
2017: うるう年ではありません。

Time APIで判定

Java 8以降のバージョンではTime APIが用意されています。ここでは、LocalDateクラスを使って判定する方法を載せます。

このクラスにはof(int year, int month, int dayOfMonth)というstaticメソッドが用意されています。引数で年、月、日を指定し、LocalDateのインスタンスが返却されます。

with(TemporalAdjuster adjuster)というメソッドが用意されていて、with(TemporalAdjusters.lastDayOfMonth())と記述すると、日にちが月末に設定されたLocalDateオブジェクトが返却されます。このオブジェクトに対して、getDayOfMonth()メソッドを呼び出せば、日数が取得できます。あとは29日なのかを判定するだけです。

例えば、次のように実装できます。

Time API

	public static boolean judge(int year) {
		// オブジェクト生成
		LocalDate localDate = LocalDate.of(year, 2, 1);
		// 日数を取得
		int numberOfdays = localDate.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
		// 日数が29日の場合、trueを返却
		return numberOfdays == 29;
	}

どちらの方法が速いのか

以下のプログラムで速さを比較してみました。

速さ比較

public class Test {

	public static void main(String[] args) {
		long start, end;
		int year = 2000;
		int max = 300000;
        start = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
        	judgeByCalendar(year);
        }
        end = System.currentTimeMillis();
        System.out.println("Calendar: " + (end - start));

        start = System.currentTimeMillis();
        for (int i = 0; i < max; i++) {
        	judgeByTimeAPI(year);
        }
        end = System.currentTimeMillis();
        System.out.println("Time API: " + (end - start));
	}

	public static boolean judgeByCalendar(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(year, Calendar.FEBRUARY, 1);
		int numberOfdays = calendar.getActualMaximum(Calendar.DATE);
		return numberOfdays == 29;
	}

	public static boolean judgeByTimeAPI(int year) {
		LocalDate localDate = LocalDate.of(year, 2, 1);
		int numberOfdays = localDate.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
		return numberOfdays == 29;
	}

}

結果

Calendar: 1125
Time API: 187

上記のようにTime APIを使った方が圧倒的に速いという結果になりました。Java 8以降ではTime APIを使った方が良いでしょう。