読者です 読者をやめる 読者になる 読者になる

倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

「日曜日から土曜日まですっぽりとハマってる月は今月が実に823年ぶり 」は本当かどうか Java 日時 API に問うてみた

Java8

2月1日にこんなツイートがありました:


で、即刻「デマだ!」というリプとかもあって「やられた」と思ったんですが、やはりこういうのは自分で確かめてみるべきだなと思い、Java8 で導入された Stream APIJava 日時 API (Java DateTime API) でこういう年を探すコードを書いてみました。

2月がカレンダーにすっぽりとハマるようになるための条件は

  • その年は閏年 (leap year) ではない
  • 2月1日が日曜日

なので、結構簡単に判定できますね。 閏年の判定はめんどくさそうにみえるけど、API に丸投げで OK。 Year#isLeap() で出来ます*1。 また、時刻は関係ないので Year や LocalDate などで充分事足りますな。 特に、最初ハードルが高そうに感じるタイムゾーンやオフセットなどは不必要。

以下のコードでは、今年(2015年)から始めて100年(range() の引数)遡って上記の条件を満たす年を表示します。

import java.util.stream.IntStream;

import java.time.Year;
import java.time.MonthDay;
import java.time.LocalDate;

import static java.time.Month.FEBRUARY;
import static java.time.DayOfWeek.SUNDAY;

public class Main {

    public static void main(String... args){
        IntStream.range(0, 100)

                .mapToObj(i -> Year.of(2015 - i))
                .filter(year -> !year.isLeap())    // 閏年かどうか

                .map(year -> year.atMonthDay(MonthDay.of(FEBRUARY, 1)))
                .filter(day -> day.getDayOfWeek() == SUNDAY)    // 2月1日が日曜かどうか

                .map(LocalDate::getYear)
                .forEach(System.out::println);
    }
}

Java 日時 API は当初不評だった気がしますが、結構使いやすいですな。 IDE の補完機能を使えばほとんどドキュメントいらず。 ちょっと JavaDoc 見たけど。

で、実行結果は

2015
2009
1998
1987
1981
1970
1959
1953
1942
1931
1925

えっ! 結構あるな(笑) 過去100年で11年。 ちなにみ過去1000年で試したら110年くらいあったヨ!

修正
コード中で int のストリームの生成方法を range() メソッドを使うように変更しました。

デートTIME

デートTIME

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

*1:YearManth#isLeapYear() など、他のクラスにも判定メソッドはあるようです。