Einführung in die Java 8 Date/Time-API

Einführung in die Java 8 Date / Time API

1. Überblick

Java 8 führte neue APIs fürDate undTime ein, um die Mängel der älterenjava.util.Date undjava.util.Calendar zu beheben.

Beginnen wir als Teil dieses Artikels mit den Problemen in den vorhandenen APIsDate undCalendarund diskutieren, wie die neuen APIs Java 8Date undTimediese beheben.

Wir werden uns auch einige der Kernklassen des neuen Java 8-Projekts ansehen, die Teil desjava.time-Pakets sind, wieLocalDate,LocalTime, LocalDateTime, ZonedDateTime, Period, Duration und deren unterstützte APIs.

Weitere Lektüre:

Arbeiten mit Datumsparametern im Frühjahr

Erfahren Sie, wie Sie mit Datumsparametern in Spring MVC arbeiten

Read more

Überprüfen Sie, ob eine Zeichenfolge ein gültiges Datum in Java ist

Sehen Sie sich verschiedene Möglichkeiten an, um zu überprüfen, ob ein String in Java ein gültiges Datum ist

Read more

2. Probleme mit den vorhandenen APIsDate /Time

  • Thread Safety - Die KlassenDate undCalendar sind nicht threadsicher, sodass Entwickler sich mit den Kopfschmerzen schwer zu debuggender Parallelitätsprobleme befassen und zusätzlichen Code schreiben müssen, um die Thread-Sicherheit zu gewährleisten. Im Gegenteil, die in Java 8 eingeführten neuen APIsDate undTime sind unveränderlich und threadsicher, wodurch den Entwicklern die Kopfschmerzen bei der Parallelität genommen werden.

  • APIs Design and Ease of Understanding - Die APIsDate undCalendar sind schlecht mit unzureichenden Methoden für die Ausführung der täglichen Operationen ausgelegt. Die neuenDate/Time-APIs sind ISO-zentriert und folgen konsistenten Domänenmodellen für Datum, Uhrzeit, Dauer und Zeiträume. Es gibt eine Vielzahl von Dienstprogrammmethoden, die die gängigsten Vorgänge unterstützen.

  • ZonedDate and Time - Entwickler mussten zusätzliche Logik schreiben, um die Zeitzonenlogik mit den alten APIs zu verarbeiten, während mit den neuen APIs die Behandlung der Zeitzone mitLocal undZonedDate /Timeerfolgen kann. s APIs.

3. Verwenden SieLocalDate,LocalTime undLocalDateTime

Die am häufigsten verwendeten Klassen sindLocalDate,LocalTime undLocalDateTime. Wie ihre Namen andeuten, repräsentieren sie das lokale Datum / die lokale Uhrzeit aus dem Kontext des Beobachters.

Diese Klassen werden hauptsächlich verwendet, wenn die Zeitzone nicht explizit im Kontext angegeben werden muss. In diesem Abschnitt werden die am häufigsten verwendeten APIs behandelt.

3.1. Arbeiten mitLocalDate

LocalDate steht füra date in ISO format (yyyy-MM-dd) without time.

Es kann verwendet werden, um Daten wie Geburtstage und Zahltage zu speichern.

Eine Instanz des aktuellen Datums kann wie folgt über die Systemuhr erstellt werden:

LocalDate localDate = LocalDate.now();

DieLocalDate, die einen bestimmten Tag, Monat und Jahr darstellen, können mit der Methode „of“ oder mit der Methode „parse“ ermittelt werden. Zum Beispiel repräsentieren die folgenden Codefragmente dieLocalDate für den 20. Februar 2015:

LocalDate.of(2015, 02, 20);

LocalDate.parse("2015-02-20");

DasLocalDate bietet verschiedene Dienstprogrammmethoden, um eine Vielzahl von Informationen zu erhalten. Lassen Sie uns einen kurzen Blick auf einige dieser API-Methoden werfen.

Das folgende Code-Snippet ruft das aktuelle lokale Datum ab und fügt einen Tag hinzu:

LocalDate tomorrow = LocalDate.now().plusDays(1);

In diesem Beispiel wird das aktuelle Datum ermittelt und ein Monat abgezogen. Beachten Sie, wie einenum als Zeiteinheit akzeptiert wird:

LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);

In den folgenden beiden Codebeispielen analysieren wir das Datum „2016-06-12“ und erhalten den Wochentag bzw. den Tag des Monats. Beachten Sie die Rückgabewerte. Der erste ist ein Objekt, dasDayOfWeek darstellt, während der zweite inint den Ordnungswert des Monats darstellt:

DayOfWeek sunday = LocalDate.parse("2016-06-12").getDayOfWeek();

int twelve = LocalDate.parse("2016-06-12").getDayOfMonth();

Wir können testen, ob ein Datum in einem Schaltjahr liegt. In diesem Beispiel testen wir, ob das aktuelle Datum ein Schaltjahr ist:

boolean leapYear = LocalDate.now().isLeapYear();

Die Beziehung eines Datums zu einem anderen kann so festgelegt werden, dass sie vor oder nach einem anderen Datum auftritt:

boolean notBefore = LocalDate.parse("2016-06-12")
  .isBefore(LocalDate.parse("2016-06-11"));

boolean isAfter = LocalDate.parse("2016-06-12")
  .isAfter(LocalDate.parse("2016-06-11"));

Datumsgrenzen können ab einem bestimmten Datum abgerufen werden. In den folgenden zwei Beispielen erhalten wir dieLocalDateTime, die den Beginn des Tages (2016-06-12T00: 00) des angegebenen Datums darstellen, und dieLocalDate, die den Beginn des Monats (2016-) darstellen. 06-01) jeweils:

LocalDateTime beginningOfDay = LocalDate.parse("2016-06-12").atStartOfDay();
LocalDate firstDayOfMonth = LocalDate.parse("2016-06-12")
  .with(TemporalAdjusters.firstDayOfMonth());

Schauen wir uns nun an, wie wir mit der Ortszeit arbeiten.

3.2. Arbeiten mitLocalTime

LocalTime steht fürtime without a date.

Ähnlich wie beiLocalDate kann eine Instanz vonLocalTime aus der Systemuhr oder mithilfe der Methoden "parse" und "of" erstellt werden. Sehen Sie sich kurz einige der im Folgenden häufig verwendeten APIs an.

Eine Instanz von aktuellLocalTime kann wie folgt aus der Systemuhr erstellt werden:

LocalTime now = LocalTime.now();

Im folgenden Codebeispiel, erstellen wir einLocalTime, das 06:30 Uhr darstellt, indem wir eine Zeichenfolgendarstellung analysieren:

LocalTime sixThirty = LocalTime.parse("06:30");

Mit der Factory-Methode "of" könnenLocalTime erstellt werden. Mit dem folgenden Code werden beispielsweiseLocalTime für 06:30 Uhr mithilfe der Factory-Methode erstellt:

LocalTime sixThirty = LocalTime.of(6, 30);

Im folgenden Beispiel wird einLocalTime durch Parsen einer Zeichenfolge erstellt und mithilfe der Plus-API eine Stunde hinzugefügt. Das Ergebnis wäreLocalTime für 07:30 Uhr:

LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);

Es stehen verschiedene Getter-Methoden zur Verfügung, mit denen bestimmte Zeiteinheiten wie Stunde, Minute und Sekunde wie folgt ermittelt werden können:

int six = LocalTime.parse("06:30").getHour();

Wir können auch überprüfen, ob eine bestimmte Zeit vor oder nach einer anderen bestimmten Zeit liegt. Das folgende Codebeispiel vergleicht zweiLocalTime, für die das Ergebnis wahr wäre:

boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));

Die maximale, minimale und mittagszeit eines Tages kann durch Konstanten in der KlasseLocalTimeerhalten werden. Dies ist sehr nützlich, wenn Sie Datenbankabfragen durchführen, um Datensätze innerhalb eines bestimmten Zeitraums zu finden. Der folgende Code steht beispielsweise für 23: 59: 59.99:

LocalTime maxTime = LocalTime.MAX

Tauchen wir nun inLocalDateTime ein.

3.3. Arbeiten mitLocalDateTime

LocalDateTime wird verwendet, uma combination of date and time darzustellen.

Dies ist die am häufigsten verwendete Klasse, wenn wir eine Kombination aus Datum und Uhrzeit benötigen. Die Klasse bietet eine Vielzahl von APIs und wir werden uns einige der am häufigsten verwendeten ansehen.

Eine Instanz vonLocalDateTime kann von der Systemuhr ähnlich wieLocalDate undLocalTime: erhalten werden

LocalDateTime.now();

In den folgenden Codebeispielen wird erläutert, wie eine Instanz mit den Factory-Methoden "of" und "parse" erstellt wird. Das Ergebnis wäre eineLocalDateTime-Instanz, die den 20. Februar 2015, 06:30 Uhr, darstellt:

LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
LocalDateTime.parse("2015-02-20T06:30:00");

Es gibt Dienstprogramm-APIs, die das Hinzufügen und Abziehen bestimmter Zeiteinheiten wie Tage, Monate, Jahre und Minuten unterstützen. Die folgenden Codebeispiele veranschaulichen die Verwendung der Methoden "Plus" und "Minus". Diese APIs verhalten sich inLocalDate undLocalTime: genau wie ihre Gegenstücke

localDateTime.plusDays(1);
localDateTime.minusHours(2);

Getter-Methoden sind verfügbar, um bestimmte Einheiten zu extrahieren, die den Datums- und Zeitklassen ähneln. In Anbetracht der obigen Instanz vonLocalDateTime gibt das folgende Codebeispiel den Monat Februar zurück:

localDateTime.getMonth();

4. Verwenden derZonedDateTime API

Java 8 provides ZonedDateTime # [.typ] #wenn wir uns mit zeitzonenspezifischem Datum und Uhrzeit befassen müssen. ZoneId ist eine Kennung, die zur Darstellung verschiedener Zonen verwendet wird. Es gibt ungefähr 40 verschiedene Zeitzonen und dieZoneId werden verwendet, um sie wie folgt darzustellen.

In diesem Code-Snippet erstellen wir einZone für Paris:

ZoneId zoneId = ZoneId.of("Europe/Paris");

Ein Satz aller Zonen-IDs kann wie folgt abgerufen werden:

Set allZoneIds = ZoneId.getAvailableZoneIds();

DieLocalDateTime können in eine bestimmte Zone konvertiert werden:

ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);

ZonedDateTime bietet die Methodeparse zum Abrufen der zeitzonenspezifischen Datums- und Uhrzeitangabe:

ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");

Eine andere Möglichkeit, mit der Zeitzone zu arbeiten, ist die Verwendung vonOffsetDateTime. OffsetDateTime ist eine unveränderliche Darstellung einer Datums- und Uhrzeitangabe mit einem Versatz. Diese Klasse speichert alle Datums- und Zeitfelder mit einer Genauigkeit von Nanosekunden sowie den Versatz von UTC / Greenwich.

Die InstanzOffSetDateTime kann wie folgt mitZoneOffset erstellt werden. Hier erstellen wir einLocalDateTime, das am 20. Februar 2015 6:30 Uhr darstellt:

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);

Dann addieren wir zwei Stunden zur Zeit, indem wirZoneOffset erstellen und für die InstanzlocalDateTime festlegen:

ZoneOffset offset = ZoneOffset.of("+02:00");

OffsetDateTime offSetByTwo = OffsetDateTime
  .of(localDateTime, offset);

Wir haben jetzt einen Prozentsatz (t0) von 2015-02-20 06:30 +02: 00. Fahren wir nun mit dem Ändern von Datums- und Zeitwerten mithilfe der KlassenPeriod undDurationfort.

5. Verwenden vonPeriod undDuration

Die KlassePeriodrepräsentiert eine Zeitmenge in Jahren, Monaten und Tagen und die KlasseDurationrepräsentiert eine Zeitmenge in Sekunden und Nanosekunden.

5.1. Arbeiten mitPeriod

Die KlassePeriodwird häufig verwendet, um Werte eines bestimmten Datums zu ändern oder um die Differenz zwischen zwei Datumsangaben zu ermitteln:

LocalDate initialDate = LocalDate.parse("2007-05-10");

DieDate können mitPeriod bearbeitet werden, wie im folgenden Codeausschnitt gezeigt:

LocalDate finalDate = initialDate.plus(Period.ofDays(5));

Die KlassePeriod verfügt über verschiedene Getter-Methoden wiegetYears, getMonths undgetDays, um Werte von einemPeriod-Objekt abzurufen. Das folgende Codebeispiel gibt einenint-Wert von 5 zurück, wenn wir versuchen, eine Differenz in Tagen: zu erhalten

int five = Period.between(initialDate, finalDate).getDays();

DiePeriod zwischen zwei Daten können in einer bestimmten Einheit wie Tagen, Monaten oder Jahren unter Verwendung vonChronoUnit.between: ermittelt werden

long five = ChronoUnit.DAYS.between(initialDate, finalDate);

Dieses Codebeispiel gibt fünf Tage zurück. Schauen wir uns weiter dieDuration-Klasse an.

5.2. Arbeiten mitDuration

Ähnlich wie beiPeriod, wirdDuration class verwendet, um mitTime. umzugehen. Im folgenden Code erstellen wir einenLocalTime von 6:30 Uhr und fügen dann eine Dauer von 30 Sekunden hinzu aLocalTime von 06:30:30 Uhr:

LocalTime initialTime = LocalTime.of(6, 30, 0);

LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));

DieDuration zwischen zwei Zeitpunkten können entweder alsDuration oder als spezifische Einheit erhalten werden. Im ersten Codeausschnitt verwenden wir diebetween()-Methode derDuration-Klasse, um den Zeitunterschied zwischenfinalTime undinitialTime zu ermitteln und den Unterschied in Sekunden zurückzugeben:

long thirty = Duration.between(initialTime, finalTime).getSeconds();

Im zweiten Beispiel verwenden wir die Methodebetween() der KlasseChronoUnit, um dieselbe Operation auszuführen:

long thirty = ChronoUnit.SECONDS.between(initialTime, finalTime);

Nun werden wir uns ansehen, wie vorhandeneDate undCalendar in neueDate /Time. konvertiert werden

6. Kompatibilität mitDate undCalendar

Java 8 hat die MethodetoInstant()hinzugefügt, mit der vorhandene Instanzen vonDate undCalendarwie im folgenden Codefragment in eine neue Datums- / Uhrzeit-API konvertiert werden können:

LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());

DieLocalDateTime können aus Epochensekunden wie folgt konstruiert werden. Das Ergebnis des folgenden Codes wäreLocalDateTime für 2016-06-13T11: 34: 50:

LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);

Fahren wir nun mit der Formatierung vonDate undTimefort.

7. Date undTime Formatierung

Java 8 bietet APIs für die einfache Formatierung vonDate undTime: __

LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);

Der folgende Code übergibt ein ISO-Datumsformat, um das lokale Datum zu formatieren. Das Ergebnis wäre der 25.01.2015:

String localDateString = localDateTime.format(DateTimeFormatter.ISO_DATE);

DasDateTimeFormatter bietet verschiedene Standardformatierungsoptionen. Es können auch benutzerdefinierte Muster für die Formatierungsmethode bereitgestellt werden, wie unten angegeben, die einenLocalDate als 25.01.2015 zurückgeben würden:

localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

Wir können den Formatierungsstil entweder alsSHORT,LONG oderMEDIUM als Teil der Formatierungsoption übergeben. Das folgende Codebeispiel würde eine Ausgabe ergeben, dieLocalDateTime am 25. Januar 2015, 06:30:00 Uhr darstellt:

localDateTime
  .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))
  .withLocale(Locale.UK);

Schauen wir uns Alternativen an, die für Java 8 CoreDate /Time APIs verfügbar sind.

8. Backport und alternative Optionen

8.1. Verwenden von Project Threeten

Für Unternehmen, die sich auf dem Weg befinden, von Java 7 oder Java 6 auf Java 8 umzusteigen und die Datums- und Uhrzeit-API verwenden möchten, bietet projectthreeten die Backport-Funktion. Entwickler können die in diesem Projekt verfügbaren Klassen verwenden, um die gleiche Funktionalität wie bei der neuen Java 8Date undTime API zu erreichen. Sobald sie auf Java 8 umsteigen, können die Pakete umgeschaltet werden. Artefakt für das Projekt threeten finden Sie inmaven central repository:


    org.threeten
    threetenbp
    1.3.1

8.2. Joda-Time-Bibliothek

Eine andere Alternative für die Bibliothek von Java 8Date undTimeist die Bibliothek vonJoda-Time. Tatsächlich wurden die APIs von Java 8Date Timegemeinsam vom Autor der Joda-Time-Bibliothek (Stephen Colebourne) und Oracle geleitet. Diese Bibliothek bietet nahezu alle Funktionen, die im Java 8Date Time-Projekt unterstützt werden. Das Artefakt kann inmaven central gefunden werden, indem die folgende POM-Abhängigkeit in Ihr Projekt aufgenommen wird:


    joda-time
    joda-time
    2.9.4

9. Fazit

Java 8 bietet eine Vielzahl von APIs mit konsistentem API-Design für eine einfachere Entwicklung.

Die Codebeispiele für den obigen Artikel befinden sich im Git-Repository vonJava 8 Date/Time.