Java 8 hat eine völlig neue API für Datum und Uhrzeit. Eine der nützlichsten Klassen in dieser API ist LocalDateTime
, um einen zeitzonenunabhängigen Datum-mit-Zeit-Wert zu speichern.
Es gibt wahrscheinlich Millionen von Codezeilen, die zu diesem Zweck die Legacy-Klasse Java.util.Date
verwenden. Wenn Sie also alten und neuen Code miteinander verbinden, müssen Sie zwischen beiden konvertieren. Wie kann dies erreicht werden, da es anscheinend keine direkten Methoden gibt?
Kurze Antwort:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Erläuterung: (basierend auf diese Frage about LocalDate
)
Trotz seines Namens repräsentiert Java.util.Date
einen Zeitpunkt auf der Zeitachse, kein "Datum". Die tatsächlichen Daten, die in dem Objekt gespeichert sind, sind eine Anzahl von long
Millisekunden seit 1970-01-01T00: 00Z (Mitternacht zu Beginn von 1970 GMT/UTC).
Die äquivalente Klasse zu Java.util.Date
in JSR-310 ist Instant
, daher gibt es bequeme Methoden, um die Konvertierung hin und her zu ermöglichen:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
Eine Java.util.Date
-Instanz kennt keine Zeitzone. Dies mag seltsam erscheinen, wenn Sie toString()
für einen Java.util.Date
aufrufen, da toString
relativ zu einer Zeitzone ist. Diese Methode verwendet jedoch tatsächlich die Standardzeitzone von Java, um die Zeichenfolge bereitzustellen. Die Zeitzone ist nicht Teil des aktuellen Status von Java.util.Date
.
Ein Instant
enthält auch keine Informationen zur Zeitzone. Für die Konvertierung von Instant
in eine lokale Datums- und Uhrzeitzone muss daher eine Zeitzone angegeben werden. Dies kann die Standardzone sein - ZoneId.systemDefault()
- oder eine Zeitzone, die von Ihrer Anwendung gesteuert wird, z. B. eine Zeitzone aus Benutzereinstellungen. LocalDateTime
verfügt über eine praktische Factory-Methode, die sowohl den Zeitpunkt als auch die Zeitzone berücksichtigt:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Umgekehrt wird LocalDateTime
die Zeitzone durch Aufrufen der Methode atZone(ZoneId)
angegeben. Das ZonedDateTime
kann dann direkt in ein Instant
konvertiert werden:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Beachten Sie, dass die Konvertierung von LocalDateTime
in ZonedDateTime
zu unerwartetem Verhalten führen kann. Dies liegt daran, dass aufgrund der Sommerzeit nicht jede lokale Datums- und Uhrzeitangabe vorhanden ist. Im Herbst/Herbst gibt es eine Überlappung in der lokalen Zeitleiste, in der dieselbe lokale Datumszeit zweimal auftritt. Im Frühjahr gibt es eine Lücke, in der eine Stunde verschwindet. Im Javadoc von atZone(ZoneId)
finden Sie weitere Informationen zur Definition der Konvertierung.
Zusammenfassung: Wenn Sie einen Java.util.Date
zu einem LocalDateTime
und zurück zu einem Java.util.Date
umkehren, kann es aufgrund der Sommerzeit zu einem anderen Zeitpunkt kommen.
Zusätzliche Informationen: Es gibt einen weiteren Unterschied, der sich auf sehr alte Daten auswirkt. Java.util.Date
verwendet einen Kalender, der am 15. Oktober 1582 geändert wird, wobei zuvor der julianische anstelle des gregorianischen Kalenders verwendet wird. Im Gegensatz dazu verwendet Java.time.*
das ISO-Kalendersystem (entspricht dem Gregorianischen) für alle Zeiten. In den meisten Fällen ist das ISO-Kalendersystem das, was Sie möchten, aber beim Vergleichen von Daten vor dem Jahr 1582 können merkwürdige Effekte auftreten.
Folgendes habe ich mir ausgedacht (und wie bei allen Datum/Uhrzeit-Rätseln wird es wahrscheinlich aufgrund einer seltsamen Zeitzonen-Schaltjahr-Tageslicht-Anpassung widerlegt: D)
Date
<< - >> LocalDateTime
Gegeben: Date date = [some date]
(1) LocalDateTime
<< Instant
<< Date
Instant instant = Instant.ofEpochMilli(date.getTime());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
(2) Date
<< Instant
<< LocalDateTime
Instant instant = ldt.toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
Beispiel:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
LocalDateTime
<< Instant
<< Date
:Erstelle Instant
aus Date
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
Erstelle Date
aus Instant
(nicht notwendig, aber zur Veranschaulichung):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Erstelle LocalDateTime
aus Instant
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
Date
<< Instant
<< LocalDateTime
Erstelle Instant
aus LocalDateTime
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
Erstelle Date
aus Instant
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Instant from Date:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
LocalDateTime from Instant:
2013-11-01T14:13:04.574
Instant from LocalDateTime:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Viel bequemer, wenn Sie sicher sind, dass Sie eine Standard-Zeitzone benötigen:
Date d = Java.sql.Timestamp.valueOf( myLocalDateTime );
folgendes scheint zu funktionieren, wenn von der neuen API LocalDateTime in Java.util.date konvertiert wird:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
die umgekehrte Konvertierung kann (hoffentlich) auf ähnliche Weise erreicht werden ...
ich hoffe es hilft...
Alles ist hier: http://blog.progs.be/542/date-to-Java-time
Die Antwort mit "Roundtripping" ist nicht genau: wenn Sie tun
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
wenn Ihre System-Zeitzone nicht UTC/GMT ist, ändern Sie die Zeit!
Ich bin mir nicht sicher, ob dies der einfachste oder beste Weg ist oder ob es Fallstricke gibt, aber es funktioniert:
static public LocalDateTime toLdt(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
ZonedDateTime zdt = cal.toZonedDateTime();
return zdt.toLocalDateTime();
}
static public Date fromLdt(LocalDateTime ldt) {
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
GregorianCalendar cal = GregorianCalendar.from(zdt);
return cal.getTime();
}
Der schnellste Weg für LocalDateTime
-> Date
ist:
Date.from(ldt.toInstant(ZoneOffset.UTC))
Wenn Sie auf Android sind und threetenbp verwenden, können Sie stattdessen DateTimeUtils
verwenden.
ex:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
sie können Date.from
nicht verwenden, da es nur auf API 26+ unterstützt wird