webentwicklung-frage-antwort-db.com.de

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

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?

443
Knut Arne Vedaa

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.

666
JodaStephen

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)

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

Gegeben:

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

(1) 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);

(2) 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());

Die Ausgabe ist:

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
126
The Coordinator

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

Date d = Java.sql.Timestamp.valueOf( myLocalDateTime );
19
Petrychenko

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...

7
dizzy

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!

3
joe-mojo

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();
}
3
Knut Arne Vedaa

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

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

2

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

2
humazed