こんにちは。ハンドルネーム「Javaを復習する初心者」です。このサイトはプログラミング言語Javaの復習・学習をするブログです。プログラムの開発・実行はEclipseで行ってます。
スポンサーリンク
お知らせ
  • 参考文献のページ作りました。
  • Amazon.co.jpアソシエイトに参加していますが、参考文献の紹介はもしもアフィリエイトに統一しました。
  • 2016年10月9日からは投稿ペースを落とします。週1回くらいにする予定です。
スポンサーリンク

Date-Time APIで月末を取得する。

こんにちは。「Javaを復習する初心者」です。今回はJava8の機能であるDate-Time APIを使って、月末を取得する方法を書きました。

以前、「Calendarで月末を取得」という記事を書いた時、以下の2つの方法を使いました。

  1. getActualMaximumメソッドを使う。
  2. 翌月初日から-1日する。

この方法をJava8のDate-Time APIで用意されているLocalDateクラスに書き直そうとしました。2月の末日を取得する方法です。それが以下の2つです。

  1. LocalDate.of(2016, Month.FEBRUARY.getValue(), 1).range(ChronoField.DAY_OF_MONTH).getMaximum()
  2. LocalDate.of(2016, Month.MARCH.getValue(), 1).minusDays(1L).getDayOfMonth()

以前にQiitaに投稿した結果

実はlengthOfMonth()メソッドがあるのにその存在を気づかずに、上記の方法で速さを比較し、Qiitaに投稿しました。

LocalDateクラスを使って月末を取得する方法について速さを比較してみました。 実行環境は以下の通りです。 + DELL VOSTRO 1540 + Windows 10 Pro 32bit + Intel Celelron ...

その結果、コメントを頂き、「lengthOfMonth()」メソッドを教えていただきました。このメソッドで月末が取得できるのでした。また、LocalDateクラスは年月日を設定して使うのですが、java.time.YearMonthというクラスがあり、こちらは年月の設定で使えることも教えていただきました。

後で気づいたのですが、LocalDate.of()は第2引数の指定でgetValueは必要ないようです。

上記のいきさつにより、Java8では月末取得は以下の2つの方法どちらかだと思います。

  1. LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth()
  2. YearMonth.of(2016, Month.FEBRUARY).lengthOfMonth()

速さ比較

前回のCalendarクラスで実行したメソッドも含め、比較してみました。100000回繰り返した時間を計測しました。

package dataTimeApiTest;

import java.time.LocalDate;
import java.time.Month;
import java.time.YearMonth;
import java.time.temporal.ChronoField;
import java.util.Calendar;

public class HelloLastDay {

    public static void main(String[] args) {

        int loopCount = 100000;
        long startTime, endTime;

        System.out.println("java7 getActualMaximum");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java7_1();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

        System.out.println("java7 翌月初日-1");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java7_2();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

        System.out.println("java8 rangeを使う");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java8_1();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

        System.out.println("java8 翌月初日-1");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java8_2();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

        System.out.println("LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth()");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java8_3();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

        System.out.println("YearMonth.of(2016, Month.FEBRUARY).lengthOfMonth()");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            java8_4();
        }
        endTime   = System.currentTimeMillis();
        System.out.println(endTime - startTime);

    }

    private static void java7_1() {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(2016, 1, 1);
        c.getActualMaximum(Calendar.DATE);

    }

    private static void java7_2() {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(2016, 2, 1);
        c.add(Calendar.DATE, -1);
        c.get(Calendar.DATE);
    }

    private static void java8_1() {
        long lastDay = LocalDate.of(2016, Month.FEBRUARY.getValue(), 1).range(ChronoField.DAY_OF_MONTH).getMaximum();
    }

    private static void java8_2() {
        long lastDay = LocalDate.of(2016, Month.MARCH.getValue(), 1).minusDays(1L).getDayOfMonth();
    }

    private static void java8_3() {
        long lastDay = LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth();
    }

    private static void java8_4() {
        long lastDay = YearMonth.of(2016, Month.FEBRUARY).lengthOfMonth();
    }

}
java7 getActualMaximum
472
java7 翌月初日-1
300
java8 rangeを使う
92
java8 翌月初日-1
46
LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth()
6
YearMonth.of(2016, Month.FEBRUARY).lengthOfMonth()
28

上記結果を見ると、LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth()が速いです。