Java 8: Berechnen Sie die Differenz zwischen zwei ZonedDateTime

79

Ich versuche, eine Methode zum Drucken des Zeitunterschieds zwischen zwei ZonedDateTime-Daten in Bezug auf den Unterschied zwischen Zeitzonen zu schreiben .

Ich habe einige Lösungen gefunden, aber alle wurden für die Arbeit mit LocalDateTime geschrieben .

Maggie Hill
quelle
2
Veröffentlichen Sie ein konkretes Beispiel dafür, was Sie erreichen möchten, und erzielen Sie daraus ein Ergebnis.
JB Nizet
2
Michałs Antwort ist genau das, was ich erwartet habe. Danke vielmals!
Maggie Hill

Antworten:

94

Sie können die Methode zwischen von ChronoUnit verwenden .

Dieses Verfahren wandelt die Zeiten , zu derselben Zone (Zone aus dem ersten Argument) und danach ruft , bis Methode deklariert in Temporal - Schnittstelle:

static long zonedDateTimeDifference(ZonedDateTime d1, ZonedDateTime d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

Da sowohl ZonedDateTime und Local Geräte Temporal - Schnittstelle können Sie auch universelle Methode für die Datum-Zeit - Typen schreiben:

static long dateTimeDifference(Temporal d1, Temporal d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

Aber bedenken Sie , dass diese Methode für gemischte Aufrufen Local und ZonedDateTime führt zu DateTimeException .

Ich hoffe es hilft.

Michał Szewczyk
quelle
Gibt es eine Möglichkeit, den Unterschied zwischen zwei ZDT-Typen zu ermitteln, bei denen sich die ZoneId zwischen den beiden ZDTs unterscheidet?
Stanlick
@ Stanlick Ja: Duration.between( zdtA , zdtB )wie in meiner Antwort gezeigt . Ich stelle mir vor, die betweenMethode ruft einfach ZonedDateTime::toInstant()beide auf.
Basil Bourque
71

tl; dr

Für Stunden, Minuten, Sekunden:

Duration.between( zdtA , zdtB )  // Represent a span-of-time in terms of days (24-hour chunks of time, not calendar days), hours, minutes, seconds. Internally, a count of whole seconds plus a fractional second (nanoseconds).

Seit Jahren, Monaten, Tagen:

Period.between(                  // Represent a span-of-time in terms of years-months-days. 
    zdtA.toLocalDate() ,         // Extract the date-only from the date-time-zone object. 
    zdtB.toLocalDate() 
)

Einzelheiten

Die Antwort von Michal S ist richtig und zeigt ChronoUnit.

Duration & Period

Eine andere Route ist die Durationund PeriodKlassen. Verwenden Sie die erste für kürzere Zeiträume (Stunden, Minuten, Sekunden), die zweite für längere Zeit (Jahre, Monate, Tage).

Duration d = Duration.between( zdtA , zdtB );

Erstellen Sie durch Aufrufen einen String im Standardformat ISO 8601toString . Das Format ist , PnYnMnDTnHnMnSwo die Pmarkiert den Beginn und Ttrennt die beiden Teile.

String output = d.toString();

Rufen Sie in Java 9 und höher die to…PartMethoden auf, um die einzelnen Komponenten abzurufen. In einer anderen Antwort von mir besprochen .

Beispielcode

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = ZonedDateTime.now( z );
ZonedDateTime zdtStop = zdtStart.plusHours( 3 ).plusMinutes( 7 );

Duration d = Duration.between( zdtStart , zdtStop );

2016-12-11T03: 07: 50.639-05: 00 [Amerika / Montreal] /2016-12-11T06:14:50.639-05:00 [Amerika / Montreal]

PT3H7M

Siehe Live-Code in IdeOne.com .

Interval & LocalDateRange

Das ThreeTen-Extra- Projekt erweitert die java.time-Klassen um Funktionen. Eine seiner praktischen Klassen besteht Intervaldarin, eine Zeitspanne als ein Paar von Punkten auf der Zeitachse darzustellen. Ein anderer ist LocalDateRangefür ein Paar von LocalDateObjekten. Im Gegensatz dazu stellen die Period& DurationKlassen jeweils eine Zeitspanne dar, die nicht an die Zeitachse angehängt ist.

Die Factory-Methode für Intervalnimmt ein Objektpaar Instant.

Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );

Sie können eine Durationvon einem erhalten Interval.

Duration d = interval.toDuration();

Tabelle der Zeitspannenklassen in Java und im ThreeTen-Extra-Projekt


Über java.time

Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .

Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Strings, keine Notwendigkeit für java.sql.*Klassen.

Woher bekomme ich die java.time-Klassen?

Das ThreeTen-Extra- Projekt erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von java.time. Sie können einige nützliche Klassen hier wie finden Interval, YearWeek, YearQuarter, und mehr .

Basil Bourque
quelle
Wo sehen Sie eine ofMethode zur Dauer, die zwei Augenblicke dauert? Ich sehe nurpublic static Duration of(long amount, TemporalUnit unit)
Brian Gordon
@BrianGordon Behoben, ersetzt .ofdurch .between. Vielen Dank.
Basil Bourque
Die Dauer funktioniert mit ZonedDateTime, während die Periode mit LocalDate funktioniert. Für unser zdt-Objekt muss die Methode toLocalDate () aufgerufen werden.
Guillaume Guerin
1
@guillaumeguerin Du bist richtig. Mein Codebeispiel wurde behoben. Vielen Dank.
Basil Bourque
Oh Mann, vielen Dank, dein Beispiel ist ziemlich gut !!!!
Brendon Iwata