TemporalAdjuster in Java

TemporalAdjuster in Java

1. Überblick

In diesem Tutorial werfen wir einen kurzen Blick auf dieTemporalAdjuster und verwenden sie in einigen praktischen Szenarien.

Java 8 hat eine neue Bibliothek für die Arbeit mit Datum und Uhrzeit eingeführt -java.time undTemporalAdjuster sind ein Teil davon. Wenn Sie mehr überjava.time, erfahren möchten, aktivieren Siethis introductory article.

Einfach ausgedrückt istTemporalAdjuster eine Strategie zum Anpassen einesTemporal-Objekts. Bevor wir uns mit der Verwendung vonTemporalAdjuster befassen, werfen wir einen Blick auf dieTemporal-Schnittstelle selbst.

2. Temporal

EinTemporal definiert eine Darstellung eines Datums, einer Uhrzeit oder einer Kombination aus beiden, abhängig von der Implementierung, die wir verwenden werden.

Es gibt eine Reihe von Implementierungen derTemporal-Schnittstelle, darunter:

  • LocalDate - Dies ist ein Datum ohne Zeitzone

  • LocalDateTime - Dies ist ein Datum und eine Uhrzeit ohne Zeitzone

  • HijrahDate - Dies ist ein Datum im Hijrah-Kalendersystem

  • MinguoDate - Dies ist ein Datum im Minguo-Kalendersystem

  • ThaiBuddhistDate - Dies ist ein Datum im thailändischen buddhistischen Kalendersystem

3. TemporalAdjuster

Eine der in dieser neuen Bibliothek enthaltenen Schnittstellen istTemporalAdjuster.

TemporalAdjuster ist eine funktionale Schnittstelle mit vielen vordefinierten Implementierungen in der KlasseTemporalAdjusters. Die Schnittstelle verfügt über eine einzelne abstrakte Methode namensadjustInto(), die in jeder ihrer Implementierungen aufgerufen werden kann, indem einTemporal-Objekt an sie übergeben wird.

TemporalAdjuster ermöglicht es uns, komplexe Datumsmanipulationen durchzuführen. For example können wir das Datum des nächsten Sonntags, den letzten Tag des aktuellen Monats oder den ersten Tag des nächsten Jahres erhalten. Wir können dies natürlich mit den altenjava.util.Calendar tun.

Die neue API abstrahiert jedoch die zugrunde liegende Logik mithilfe ihrer vordefinierten Implementierungen. Weitere Informationen finden Sie unterJavadoc.

4. VordefinierteTemporalAdjusters

Die KlasseTemporalAdjusters verfügt über viele vordefinierte statische Methoden, die einTemporalAdjuster-Objekt zurückgeben, umTemporal-Objekte auf viele verschiedene Arten anzupassen, unabhängig von der Implementierung vonTemporal.

Hier ist eine kurze Liste dieser Methoden und eine kurze Definition davon:

  • dayOfWeekInMonth() - ein Einsteller für den ordinalen Wochentag. Zum Beispiel das Datum des zweiten Dienstag im März

  • firstDayOfMonth() - ein Einsteller für das Datum des ersten Tages des aktuellen Monats

  • firstDayOfNextMonth() - ein Einsteller für das Datum des ersten Tages des nächsten Monats

  • firstDayOfNextYear() - ein Einsteller für das Datum des ersten Tages des nächsten Jahres

  • firstDayOfYear() - ein Einsteller für das Datum des ersten Tages des laufenden Jahres

  • lastDayOfMonth() - ein Einsteller für das Datum des letzten Tages des aktuellen Monats

  • nextOrSame() - Ein Einsteller für das Datum des nächsten Auftretens eines bestimmten Wochentags oder desselben Tages, falls der heutige Tag mit dem erforderlichen Wochentag übereinstimmt

Wie wir sehen können, sind die Namen der Methoden so gut wie selbsterklärend. WeitereTemporalAdjusters finden Sie unterJavadoc.

Let’s start with a simple example - Anstatt ein bestimmtes Datum wie in den Beispielen zu verwenden, können wirLocalDate.now() verwenden, um das aktuelle Datum von der Systemuhr abzurufen.

Für dieses Tutorial verwenden wir jedoch ein festes Datum, damit die Tests später nicht fehlschlagen, wenn sich das erwartete Ergebnis ändert. Mal sehen, wie wir die KlasseTemporalAdjustersverwenden können, um das Datum des Sonntags nach dem 08.07.2017 zu erhalten:

@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());
}

So erhalten wir den letzten Tag des aktuellen Monats:

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

5. Definieren der Implementierungen von CustomTemporalAdjuster

Wir können unsere benutzerdefinierten Implementierungen auch fürTemporalAdjuster definieren. Hierfür gibt es zwei verschiedene Möglichkeiten.

5.1. Verwenden von Lambda-Ausdrücken

Mal sehen, wie wir das Datum, das 14 Tage nach dem 08.07.2017 liegt, mit der MethodeTemporal.with()ermitteln können:

@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());
}

In diesem Beispiel setzen wir mithilfe eines Lambda-Ausdrucks das ObjekttemporalAdjustero, dass es dem ObjektlocalDate, das das Datum (08.07.2017) enthält, 14 Tage hinzufügt.

Lassen Sie uns sehen, wie wir das Datum des Arbeitstages direkt nach dem 08.07.2017 erhalten können, indem wir unsere eigenenTemporalAdjuster-Implementierungen mithilfe eines Lambda-Ausdrucks definieren. Verwenden Sie diesmal jedoch die statische Factory-Methode vonofDateAdjuster():

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);
});

Testen unseres Codes:

@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. Durch Implementierung derTemporalAdjuster-Schnittstelle

Mal sehen, wie wir ein benutzerdefiniertesTemporalAdjuster schreiben können, das den Arbeitstag nach dem 08.07.2017 erhält, indem wir dieTemporalAdjuster-Schnittstelle implementieren:

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);
    }
}

Lassen Sie uns nun unseren Test ausführen:

@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. Fazit

In diesem Tutorial haben wir gezeigt, wasTemporalAdjuster ist, vordefinierteTemporalAdjusters,, wie sie verwendet werden können und wie wir die Implementierungen unserer benutzerdefiniertenTemporalAdjusterauf zwei verschiedene Arten implementieren können.

Die vollständige Implementierung dieses Tutorials finden Sie inover on GitHub.