Java 8: Berechnen des Unterschieds zwischen zwei LocalDateTime
Ich versuche zur Berechnung der Differenz zwischen zwei LocalDateTime
.
Die Ausgabe muss dem format y years m months d days h hours m minutes s seconds
. Hier ist, was ich geschrieben habe:
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
public class Main {
static final int MINUTES_PER_HOUR = 60;
static final int SECONDS_PER_MINUTE = 60;
static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
public static void main(String[] args) {
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
Period period = getPeriod(fromDateTime, toDateTime);
long time[] = getTime(fromDateTime, toDateTime);
System.out.println(period.getYears() + " years " +
period.getMonths() + " months " +
period.getDays() + " days " +
time[0] + " hours " +
time[1] + " minutes " +
time[2] + " seconds.");
}
private static Period getPeriod(LocalDateTime dob, LocalDateTime now) {
return Period.between(dob.toLocalDate(), now.toLocalDate());
}
private static long[] getTime(LocalDateTime dob, LocalDateTime now) {
LocalDateTime today = LocalDateTime.of(now.getYear(),
now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond());
Duration duration = Duration.between(today, now);
long seconds = duration.getSeconds();
long hours = seconds / SECONDS_PER_HOUR;
long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
long secs = (seconds % SECONDS_PER_MINUTE);
return new long[]{hours, minutes, secs};
}
}
Den Ausgang, bin ich immer 29 years 8 months 24 days 12 hours 0 minutes 50 seconds
. Ich habe mein Ergebnis von dieser website (mit Werten 12/16/1984 07:45:55
und 09/09/2014 19:46:45
). Der folgende screenshot zeigt die Ausgabe:
Ich bin mir ziemlich sicher, dass die Felder nach dem Monat Wert ist kommen falsch von meinem code. Jeder Vorschlag wäre sehr hilfreich.
Update
Habe ich getestet, mein Ergebnis von einer anderen website und das Ergebnis bekam ich, anders. Hier ist es: Berechnen Sie die Dauer zwischen zwei Datumsangaben (Ergebnis: 29 Jahre, 8 Monaten, 24 Tagen, 12 Stunden, 0 Minuten und 50 Sekunden).
Update
Da hab ich zwei verschiedene Ergebnisse mit zwei verschiedenen Seiten, ich Frage mich, ob der Algorithmus meiner Berechnung legitim ist oder nicht. Wenn ich folgende zwei LocalDateTime
Objekte:
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
Dann die Ausgabe kommen: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.
Aus diesem link es sollte 29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds
. So muss der Algorithmus zu handhaben, die negative zahlen zu.
Hinweis: die Frage ist nicht, über die Website gab mir, was ich wissen müssen, den richtigen Algorithmus und müssen das Recht haben, die Ergebnisse.
- Nur eine Vermutung, aber könnte
Period.between()
gelten einige der Rundung? - Ich sah den code noch einmal ein und es scheint, dass die Webseite falsch ist (Versuchen Sie die Berechnung selbst). Wenn du weglassen, das Datum, d.h. Unterschiede in der Jahr, Monat und Tag, erhalten Sie die Startzeit
7:45:55
und das Ende der Zeit19:46:45
(oder7:46:45
Uhr). Also der Unterschied zwischen denen zwei mal 12 Stunden, 0 Minuten und 50 Sekunden und nie 23 Stunden, 34 Minuten und 12 Sekunden. Also deine Berechnung actualle scheint richtig zu sein, zumindest auf den Teil der Zeit. - Interessantes Phänomen auf dieser website: hinzufügen von 10 Jahren ab Datum und die Differenz in Stunden änderungen von 23 auf 8 - sicher ein Zeichen für Fehler.
- Hinzugefügt vor 1 Jahr, 4 und 10 - keine Veränderung in Stunden
- hast du den zweiten link in meinem update?
- Beachten Sie, dass seit
LocalDateTime
hat kein Zeit-zone, könnte es nicht sein, eine eindeutige Antwort. Auch wenn Sie davon ausgehen, die start-und end-Zeit-Zonen sind die gleichen, in bestimmten Zonen Termine wie 2014-09-09 werden in der Sommerzeit oder Sommerzeit, in anderen nicht. Dies mag throw-off Dinge, indem Sie eine Stunde. Also das berechnen der Differenz der zweite ist sinnlos, es sei denn, dies ist gelöst. - "ich habe getestet, mein Ergebnis von einer anderen website und das Ergebnis bekam ich, anders" > So, dass die mit Ihrem Java-code. Scheint, wie diese Frage ist nun überflüssig - die andere website ist gebrochen.
- bitte siehe update, die Frage ist nicht redundant.
- dann muss ich verwenden
ZonedDateTime
; richtig? - wenn man sich den code für das Datum abrufen Zeit werden Sie feststellen, dass der Teil entfernt wird und somit nur das Datum betrachtet. Das ist, warum Sie bekommen 24 Tage statt 23.
ZonedDateTime
wird Ihnen helfen zu vermeiden das bestimmte problem, das ich erwähnte.- Was
java.time.Duration.between(Temporal a, Temporal b)
? Laut javadoc: Erhält eine Dauer der Vertretung die Dauer zwischen zwei zeitlichen Objekten. Dieser berechnet die Dauer zwischen zwei zeitlichen Objekten. Wenn die Objekte verschiedener Typen enthalten, dann wird die Dauer berechnet, basierend auf dem Typ des ersten Objekts. Zum Beispiel, wenn das erste argument ein LocalTime dann das zweite argument ist in einer LocalTime. - Verstehen Sie, dass die Verwendung
LocalDateTime
Erträge unrealistischen Ergebnisse, wie die Klasse absichtlich fehlt jede Vorstellung von Zeit zone oder offset-von-UTC? Für realistische Werte, weisen eine Zeitzone überZoneId
zu verwendenZonedDateTime
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Leider scheint es nicht eine Periode, in der Klasse, die sich über die Zeit als gut, so müssen Sie möglicherweise führen Sie die Berechnungen auf Ihrem eigenen.
Forunately das Datum und die Zeit, die Klassen haben eine Menge von utility-Methoden, die Vereinfachung, die zu einem gewissen Grad. Hier ist ein Weg, um die Differenz zu ermitteln, wenngleich Sie nicht unbedingt der Schnellste:
Die grundlegende Idee ist folgende: erstellen Sie einen temporären Startdatum und in den vollen Jahren zu Ende. Stellen Sie dann das Datum ein, indem Sie die Anzahl der Jahre, so dass das start-Datum ist weniger als ein Jahr nach dem Ende. Wiederholen Sie, dass für jede Zeiteinheit, in absteigender Reihenfolge.
Endlich mal ein disclaimer: ich habe keine unterschiedlichen Zeitzonen zu berücksichtigen (beide Daten sollten in der gleichen Zeitzone) und ich auch nicht testen/überprüfen, wie die Sommerzeit ein -, oder andere änderungen in einem Kalender (wie die Zeitzone ändert sich in Samoa) Einfluss auf diese Berechnung. So nutzen Sie mit Sorgfalt.
ChronoUnit
, die Teil derjava.time
, als vorgestellt von satnam.ChronoUnit
🙂 aber tut den job "von hand".long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
zurückkehren würde, eine Zahl, die größer als 59 werden für jedes Intervall von mindestens 1 Stunde - und das ist nicht das, was der OP will. Nehmen Sie in account, Sie würden nicht in der Lage, nur 6 AufrufeChronoUnit#between()
und durchgeführt werden.Ich fand die beste Weg, dies zu tun ist mit ChronoUnit.
Zusätzliche Dokumentation ist hier: https://docs.oracle.com/javase/tutorial/datetime/iso/period.html
tempDateTime.until( toDateTime, ChronoUnit.YEARS)
mitChronoUnit.YEARS.between(fromDate, toDate)
. Aber das wichtige zusätzliche Zeilen wietempDateTime.plusYears( years )
etc. völlig fehlt in deiner Antwort, damit es nicht zur OP. Der vollständige Algorithmus ist wichtig!ChronoUnit.between(...)
ist nichts neues, sondern finden mehrmals hier auf die SO Beispiel-link mit einer Antwort von dem Haupt-Autor von JSR-310Hier ein einzelnes Beispiel für die Verwendung Dauer und TimeUnit um 'hh:mm:ss' - format.
String.format("%02d:%02d:%02d",dur.toHoursPart(), dur.toMinutesPart(), dur.toSecondsPart());
. Der Teil Methoden geben Ihnen die richtigen zahlen zu bauen, die einen string. Ich denke, dass es' mehr lesbar.Es sollte einfacher sein!
Und die version von @Thomas in Groovy mit die gewünschten Einheiten in einer Liste statt hardcoding die Werte. Diese Umsetzung (die leicht portiert auf Java - ich habe die Deklaration der Funktion explicit) macht Thomas Ansatz mehr wiederverwendbar.
Zum Zeitpunkt des Schreibens dieses Artikels,ist der code oben gibt
47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis
. Und für @Gennadi Kolomoets Eingang, gibt der code23 Hours
.Wenn Sie eine Liste der Einheiten, es muss sortiert werden, indem die Größe der Einheiten (größte zuerst):
Hier ist eine sehr einfache Antwort auf Ihre Frage. Es funktioniert.
Gibt es einige problem für Tapas Bose-code und Thomas-code. Wenn die Zeitdifferenz negativ ist, wird der array bekommt die negativen Werte. Zum Beispiel, wenn
gibt es 0 Jahre 0 Monate 1 Tage, -1 Stunden, 0 Minuten, 0 Sekunden.
Denke ich die richtige Ausgabe ist: 0 Jahre 0 Monate 0 Tage 23 Stunden 0 Minuten 0 Sekunden.
Ich schlage vor, trennen Sie die LocalDateTime-Instanzen auf LocalDate und LocalTime-Instanzen. Nachdem wir das Java-8 Zeit und Dauer-Instanzen. Die Dauer Instanz wird getrennt auf die Anzahl der Tage und während-den-Tag-Zeit-Wert (< 24h) mit anschließender Korrektur der Zeit-Wert. Wenn die zweite LocalTime-Wert ist vor der firstLocalTime Wert, ist es notwendig, reduzieren Sie die Zeit für einen Tag.
Hier ist mein Weg zur Berechnung der LocalDateTime Unterschied:
Dem obigen Verfahren können verwendet werden, um die Differenz zu ermitteln, alle lokalen Datum und Zeit Werte, zum Beispiel:
Ist es zweckmäßig, schreiben Sie einen unit-test für die oben genannten-Methode (beide sind PeriodDuration Schüler). Hier ist der code:
}
Alle tests erfolgreich sind, ob oder nicht der Wert des ersten LocalDateTime ist vor und für jede LocalTime Werte.
java.time.Period
wo die Benutzer erzwingen/erzeugen solche gemischten Zeichen, aufgrund von verschiedenen internen design).