覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Java - ある月の最初の〇曜日・最後の〇曜日 の日付を取得したい

例えば、ある月の最初の水曜日の日付を取得したい、ある月の最後の水曜日の日付を取得したい。
というケースが出てくる場合があります。

それを Java でやるサンプルです。

こういった場合は、java.time.temporal.TemporalAdjusters クラスを利用するのがよいです。

TemporalAdjusters で提供されているメソッドで日付を調整して目的の日付を導き出すのがよいと思います。


ある月の最初の〇曜日の日付を取得する

流れとしては、
A) 起点となる日付を設定 → B) その月の最初の日を取得 → C) 最初の日以後で最初に対象の曜日が出てくる日付を取得
という感じになります

C) の "最初の日以後" には 月の最初の日も含まれます(=月の最初の日が目的の曜日なら、その日付を取得する)

上記の処理の流れの B, C は以下のようにして実現できます

  • B: その月の最初の日を取得
    • TemporalAdjusters.firstDayOfMonth を使用することで実現できます。
  • C: 最初の日以後で最初に対象の曜日が出てくる日付を取得
    • 月の最初の日の日付を起点にして TemporalAdjusters.nextOrSame を使用することで実現できます


コードサンプルは以下のようになります。

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

import static java.time.temporal.TemporalAdjusters.firstDayOfMonth;
import static java.time.temporal.TemporalAdjusters.nextOrSame;

public class Sample1 {

    public static void main(String[] args) {
        // 起点となる日付(ここでは現在日付)
        LocalDate baseDate = LocalDate.now();

        // 対象の月の最初の日付
        LocalDate firstDayOfMonth = baseDate.with(firstDayOfMonth());

        LocalDate firstWedDayOfMonth = firstDayOfMonth.with(nextOrSame(DayOfWeek.WEDNESDAY));
        LocalDate firstThDayOfMonth = firstDayOfMonth.with(nextOrSame(DayOfWeek.THURSDAY));
        LocalDate firstFrDayOfMonth = firstDayOfMonth.with(nextOrSame(DayOfWeek.FRIDAY));
        LocalDate firstMoDayOfMonth = firstDayOfMonth.with(nextOrSame(DayOfWeek.MONDAY));

        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最初の日付は -> " + firstDayOfMonth);

        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最初の水曜日の日付は -> " + firstWedDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最初の木曜日の日付は -> " + firstThDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最初の金曜日の日付は -> " + firstFrDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最初の月曜日の日付は -> " + firstMoDayOfMonth);
    }

}


■実行結果 (の例)

(ここでは最初の起点となっている日付が 2022年3月になっています)

2022年3月 の最初の日付は -> 2022-03-01
2022年3月 の最初の水曜日の日付は -> 2022-03-02
2022年3月 の最初の木曜日の日付は -> 2022-03-03
2022年3月 の最初の金曜日の日付は -> 2022-03-04
2022年3月 の最初の月曜日の日付は -> 2022-03-07

2022年3月の最初の水曜日、木曜日、金曜日、月曜日の日付が取得できています。


ある月の最後の〇曜日の日付を取得する

流れとしては、
A) 起点となる日付を設定 → B) その月の最終日を取得 → C) 最終日以前で最初に対象の曜日が出てくる日付を取得
という感じになります

C) の "最終日以前" には 最終日も含まれます(=月の最終日が目的の曜日なら、その日付を取得する)

上記の処理の流れの B, C は以下のようにして実現できます

  • B: その月の最終日を取得
    • TemporalAdjusters.lastDayOfMonth を使用することで実現できます。
  • C: 最終日以前で最初に対象の曜日が出てくる日付を取得
    • 月の最終日の日付を起点にして TemporalAdjusters.previousOrSame を使用することで実現できます


コードサンプルは以下のようになります。

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

import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;
import static java.time.temporal.TemporalAdjusters.previousOrSame;

public class Sample2 {

    public static void main(String[] args) {
        // 起点となる日付(ここでは現在日付)
        LocalDate baseDate = LocalDate.now();

        // 対象の月の最終日
        LocalDate lastDayOfMonth = baseDate.with(lastDayOfMonth());

        LocalDate lastWedDayOfMonth = lastDayOfMonth.with(previousOrSame(DayOfWeek.WEDNESDAY));
        LocalDate lastThDayOfMonth = lastDayOfMonth.with(previousOrSame(DayOfWeek.THURSDAY));
        LocalDate lastFrDayOfMonth = lastDayOfMonth.with(previousOrSame(DayOfWeek.FRIDAY));
        LocalDate lastMoDayOfMonth = lastDayOfMonth.with(previousOrSame(DayOfWeek.MONDAY));

        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最終日の日付は -> " +  lastDayOfMonth);

        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最終水曜日の日付は -> " +  lastWedDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最終木曜日の日付は -> " +  lastThDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最終金曜日の日付は -> " +  lastFrDayOfMonth);
        System.out.println(baseDate.format(DateTimeFormatter.ofPattern("yyyy年M月")) + " の最終月曜日の日付は -> " +  lastMoDayOfMonth);
    }

}


■実行結果 (の例)

(ここでは最初の起点となっている日付が 2022年3月になっています)

2022年3月 の最終日の日付は -> 2022-03-31
2022年3月 の最終水曜日の日付は -> 2022-03-30
2022年3月 の最終木曜日の日付は -> 2022-03-31
2022年3月 の最終金曜日の日付は -> 2022-03-25
2022年3月 の最終月曜日の日付は -> 2022-03-28

2022年3月の最終の水曜日、木曜日、金曜日、月曜日の日付が取得できています。


まとめ

java.time.temporal.TemporalAdjusters クラスを利用することで無事にもとめたい日付が取得できました。
TemporalAdjusters には他にも有用なメソッドがあるようなので、色々と試してみたいとこです。



関連エントリ