613 Stimmen

Konvertierung zwischen java.time.LocalDateTime und java.util.Date

Java 8 hat eine völlig neue API für Datum und Zeit. Einer der nützlichsten Klassen in dieser API ist LocalDateTime, zum Halten eines zeitzoneunabhängigen Datumszeitwerts.

Es gibt wahrscheinlich Millionen von Codezeilen, die die veraltete Klasse java.util.Date für diesen Zweck verwenden. Daher wird es beim Schnittstellen von altem und neuem Code eine Notwendigkeit geben, zwischen den beiden zu konvertieren. Da es anscheinend keine direkten Methoden zur Erledigung gibt, wie kann dies erreicht werden?

895voto

JodaStephen Punkte 57302

Kurze Antwort:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

Erklärung: (basierend auf dieser Frage über LocalDate)

Trotz seines Namens repräsentiert java.util.Date einen Zeitpunkt auf der Zeitachse, nicht ein "Datum". Die tatsächlichen Daten, die im Objekt gespeichert sind, sind eine long Zählung von Millisekunden seit 1970-01-01T00:00Z (Mitternacht am Anfang von 1970 GMT/UTC).

Die äquivalente Klasse zu java.util.Date in JSR-310 ist Instant, daher gibt es praktische Methoden, um die Konvertierung hin und zurück zu ermöglichen:

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

Ein java.util.Date Instanz hat kein Konzept der Zeitzone. Das mag seltsam erscheinen, wenn Sie toString() auf einem java.util.Date aufrufen, weil das toString relativ zu einer Zeitzone ist. Jedoch verwendet diese Methode tatsächlich die Standard-Zeitzone von Java, um den String bereitzustellen. Die Zeitzone ist kein Teil des tatsächlichen Zustands von java.util.Date.

Ein Instant enthält auch keine Informationen über die Zeitzone. Daher ist es notwendig, beim Konvertieren von einem Instant zu einem lokalen Datum und Zeit eine Zeitzone anzugeben. Dies kann die Standardzone sein - ZoneId.systemDefault() - oder es kann eine Zeitzone sein, die Ihre Anwendung kontrolliert, wie zum Beispiel eine Zeitzone aus den Benutzereinstellungen. LocalDateTime hat eine praktische Fabrikmethode, die sowohl den Zeitpunkt als auch die Zeitzone akzeptiert:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

Umgekehrt wird die Zeitzone in LocalDateTime durch Aufrufen der Methode atZone(ZoneId) festgelegt. Der ZonedDateTime kann dann direkt in einen Instant umgewandelt werden:

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

Bemerken Sie, dass die Konvertierung von LocalDateTime zu ZonedDateTime das Potenzial hat, unerwartetes Verhalten einzuführen. Dies liegt daran, dass nicht jede lokale Datum und Zeit aufgrund der Sommerzeit existiert. Im Herbst gibt es eine Überlappung in der lokalen Zeitachse, wo dieselbe lokale Datum und Zeit zweimal vorkommt. Im Frühjahr gibt es eine Lücke, wo eine Stunde verschwindet. Sehen Sie sich die Javadoc von atZone(ZoneId) für die Definition dessen an, was die Konvertierung tun wird.

Zusammenfassend, wenn Sie eine java.util.Date zu einem LocalDateTime und zurück zu einem java.util.Date umreisen, könnten Sie aufgrund der Sommerzeit einen anderen Zeitpunkt erhalten.

Zusätzliche Informationen: Es gibt einen weiteren Unterschied, der sehr alte Daten betreffen wird. java.util.Date verwendet einen Kalender, der sich am 15. Oktober 1582 ändert, wobei Daten vor diesem Datum den julianischen Kalender anstelle des gregorianischen verwenden. Im Gegensatz dazu verwendet java.time.* das ISO-Kalendersystem (äquivalent zum gregorianischen) für alle Zeiten. In den meisten Anwendungsfällen ist das ISO-Kalendersystem das, was Sie wollen, aber Sie können merkwürdige Effekte sehen, wenn Sie Daten vor dem Jahr 1582 vergleichen.

167voto

The Coordinator Punkte 12577

Hier ist, was ich herausgefunden habe (und wie bei allen Datum-Uhrzeit-Rätseln wird es wahrscheinlich aufgrund einiger seltsamer Zeitzone-Schaltjahr-Tageslichtanpassungen widerlegt :D)

Round-tripping: Date <<->> LocalDateTime

Gegeben: Date date = [irgendein Datum]

(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:

Gegeben:

Date date = new Date();
System.out.println(date + " lang: " + date.getTime());

(1) LocalDateTime << Instant<< Date:

Erstelle Instant aus Date:

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant aus Date:\n" + instant);

Erstelle Date aus Instant (nicht notwendig, aber zur Veranschaulichung):

date = Date.from(instant);
System.out.println("Datum aus Instant:\n" + date + " lang: " + date.getTime());

Erstelle LocalDateTime aus Instant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime aus Instant:\n" + ldt);

(2) Date << Instant << LocalDateTime

Erstelle Instant aus LocalDateTime:

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant aus LocalDateTime:\n" + instant);

Erstelle Date aus Instant:

date = Date.from(instant);
System.out.println("Datum aus Instant:\n" + date + " lang: " + date.getTime());

Die Ausgabe ist:

Fr 01. Nov 07:13:04 PDT 2013 lang: 1383315184574

Instant aus Date:
2013-11-01T14:13:04.574Z

Datum aus Instant:
Fr 01. Nov 07:13:04 PDT 2013 lang: 1383315184574

LocalDateTime aus Instant:
2013-11-01T14:13:04.574

Instant aus LocalDateTime:
2013-11-01T14:13:04.574Z

Datum aus Instant:
Fr 01. Nov 07:13:04 PDT 2013 lang: 1383315184574

29voto

Petrychenko Punkte 423

Viel bequemer, wenn Sie sicher sind, dass Sie eine Standard-Zeitzone benötigen:

Datum d = java.sql.Timestamp.valueOf( myLocalDateTime );

14voto

Lukasz Czerwinski Punkte 11167

Der schnellste Weg für LocalDateTime -> Date ist:

Date.from(ldt.toInstant(ZoneOffset.UTC))

8voto

joe-mojo Punkte 101

Alles ist hier: http://blog.progs.be/542/date-to-java-time

Die Antwort mit "round-tripping" ist nicht genau: wenn du das machst

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

wenn deine Systemzeitzone nicht UTC/GMT ist, änderst du die Zeit!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X