JavaのTemporalAdjuster

JavaのTemporalAdjuster

1. 概要

このチュートリアルでは、TemporalAdjusterを簡単に見て、いくつかの実用的なシナリオで使用します。

Java 8では、日付と時刻を操作するための新しいライブラリが導入されました。java.timeTemporalAdjusterはその一部です。 java.time,について詳しく知りたい場合は、this introductory article.を確認してください。

簡単に言えば、TemporalAdjusterTemporalオブジェクトを調整するための戦略です。 TemporalAdjusterの使用法に入る前に、Temporalインターフェース自体を見てみましょう。

2. Temporal

Temporalは、使用する実装に応じて、日付、時刻、または両方の組み合わせの表現を定義します。

Temporalインターフェースには、次のような多くの実装があります。

  • LocalDate –タイムゾーンのない日付を表します

  • LocalDateTime –タイムゾーンのない日付と時刻を表します

  • HijrahDate –これはヒジュラカレンダーシステムの日付を表します

  • MinguoDate –これはMinguoカレンダーシステムの日付を表します

  • ThaiBuddhistDate –タイの仏暦システムの日付を表します

3. TemporalAdjuster

この新しいライブラリに含まれているインターフェイスの1つはTemporalAdjusterです。

TemporalAdjusterは、TemporalAdjustersクラスに多くの事前定義された実装がある関数型インターフェースです。 インターフェイスには、Temporalオブジェクトを渡すことにより、その実装のいずれかで呼び出すことができるadjustInto()という名前の単一の抽象メソッドがあります。

TemporalAdjusterを使用すると、複雑な日付操作を実行できます。 For exampleの場合、次の日曜日、当月の最終日、または翌年の初日を取得できます。 もちろん、古いjava.util.Calendarを使用してこれを行うことができます。

ただし、新しいAPIは、事前定義された実装を使用して、基になるロジックを抽象化します。 詳細については、Javadocにアクセスしてください。

4. 事前定義されたTemporalAdjusters

クラスTemporalAdjustersには、TemporalAdjusterオブジェクトを返す多くの定義済み静的メソッドがあり、Temporalの実装に関係なく、さまざまな方法でTemporalオブジェクトを調整します。

これらのメソッドの短いリストとそれらの簡単な定義は次のとおりです。

  • dayOfWeekInMonth() –通常の曜日の調整。 たとえば、3月の第2火曜日の日付

  • firstDayOfMonth() –当月の初日の日付の調整

  • firstDayOfNextMonth() –翌月の初日の日付の調整

  • firstDayOfNextYear() –翌年の初日の日付の調整

  • firstDayOfYear() –現在の年の初日の日付の調整

  • lastDayOfMonth() –当月の最終日の日付の調整

  • nextOrSame() –特定の曜日の次の発生日、または今日が必要な曜日と一致する場合は同じ日のアジャスター

ご覧のとおり、メソッドの名前はほとんど一目瞭然です。 その他のTemporalAdjustersについては、Javadocにアクセスしてください。

Let’s start with a simple example –例のように特定の日付を使用する代わりに、LocalDate.now()を使用してシステムクロックから現在の日付を取得できます。

ただし、このチュートリアルでは、期待される結果が変更されたときにテストが後で失敗しないように、固定の日付を使用します。 TemporalAdjustersクラスを使用して、2017年7月8日以降の日曜日の日付を取得する方法を見てみましょう。

@Test
public void whenAdjust_thenNextSunday() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    LocalDate nextSunday = localDate.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

    String expected = "2017-07-09";

    assertEquals(expected, nextSunday.toString());
}

今月の最終日を取得する方法は次のとおりです。

LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());

5. カスタムTemporalAdjuster実装の定義

TemporalAdjusterのカスタム実装を定義することもできます。 これを行うには2つの異なる方法があります。

5.1. ラムダ式の使用

Temporal.with()メソッドを使用して、2017年7月8日から14日後の日付を取得する方法を見てみましょう。

@Test
public void whenAdjust_thenFourteenDaysAfterDate() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    TemporalAdjuster temporalAdjuster = t -> t.plus(Period.ofDays(14));
    LocalDate result = localDate.with(temporalAdjuster);

    String fourteenDaysAfterDate = "2017-07-22";

    assertEquals(fourteenDaysAfterDate, result.toString());
}

この例では、ラムダ式を使用して、日付(2017-07-08)を保持するlocalDateオブジェクトに14日を追加するようにtemporalAdjusterオブジェクトを設定します。

ラムダ式を使用して独自のTemporalAdjuster実装を定義することにより、2017年7月8日直後の営業日の日付を取得する方法を見てみましょう。 ただし、今回は、ofDateAdjuster()静的ファクトリメソッドを使用します。

static TemporalAdjuster NEXT_WORKING_DAY = TemporalAdjusters.ofDateAdjuster(date -> {
    DayOfWeek dayOfWeek = date.getDayOfWeek();
    int daysToAdd;
    if (dayOfWeek == DayOfWeek.FRIDAY)
        daysToAdd = 3;
    else if (dayOfWeek == DayOfWeek.SATURDAY)
        daysToAdd = 2;
    else
        daysToAdd = 1;
    return today.plusDays(daysToAdd);
});

コードのテスト:

@Test
public void whenAdjust_thenNextWorkingDay() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    TemporalAdjuster temporalAdjuster = NEXT_WORKING_DAY;
    LocalDate result = localDate.with(temporalAdjuster);

    assertEquals("2017-07-10", date.toString());
}

5.2. TemporalAdjusterインターフェイスを実装する

TemporalAdjusterインターフェースを実装することにより、2017-07-08以降の稼働日を取得するカスタムTemporalAdjusterを作成する方法を見てみましょう。

public class CustomTemporalAdjuster implements TemporalAdjuster {

    @Override
    public Temporal adjustInto(Temporal temporal) {
        DayOfWeek dayOfWeek
          = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));

        int daysToAdd;
        if (dayOfWeek == DayOfWeek.FRIDAY)
            daysToAdd = 3;
        else if (dayOfWeek == DayOfWeek.SATURDAY)
            daysToAdd = 2;
        else
            daysToAdd = 1;
        return temporal.plus(daysToAdd, ChronoUnit.DAYS);
    }
}

それでは、テストを実行しましょう。

@Test
public void whenAdjustAndImplementInterface_thenNextWorkingDay() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    CustomTemporalAdjuster temporalAdjuster = new CustomTemporalAdjuster();
    LocalDate nextWorkingDay = localDate.with(temporalAdjuster);

    assertEquals("2017-07-10", nextWorkingDay.toString());
}

6. 結論

このチュートリアルでは、TemporalAdjusterとは何か、事前定義されたTemporalAdjusters,の使用方法、およびカスタムTemporalAdjusterの実装を2つの異なる方法で実装する方法を示しました。

このチュートリアルの完全な実装はover on GitHubにあります。