こんにちは。「Javaを復習する初心者」です。
今回はJava8の機能であるDate-Time APIを使って、月末を取得する方法を書きました。
きっかけ
以前、「Calendarで月末を取得」という記事を書いた時、以下の2つの方法を使いました。
- getActualMaximumメソッドを使う。
- 翌月初日から-1日する。
この方法をJava8のDate-Time APIで用意されているLocalDateクラスに書き直そうとしました。2月の末日を取得する方法です。それが以下の2つです。
- LocalDate.of(2016, Month.FEBRUARY.getValue(), 1).range(ChronoField.DAY_OF_MONTH).getMaximum()
- LocalDate.of(2016, Month.MARCH.getValue(), 1).minusDays(1L).getDayOfMonth()
実はlengthOfMonth()メソッドがあるのにその存在を気づかずに、上記の方法で速さを比較し、Qiitaに投稿しました。
https://qiita.com/java-beginner/items/e970a3d75de44413ab09
その結果、コメントを頂き、「lengthOfMonth()」メソッドを教えていただきました。このメソッドで月末が取得できるのでした。また、LocalDateクラスは年月日を設定して使うのですが、java.time.YearMonthというクラスがあり、こちらは年月の設定で使えることも教えていただきました。
後で気づいたのですが、LocalDate.of()は第2引数の指定でgetValueは必要ないようです。
上記のいきさつにより、Java8では月末取得は以下の2つの方法どちらかだと思います。
- LocalDate.of(2016, Month.FEBRUARY, 1).lengthOfMonth()
- 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()が速いです。