Soll ich java.util.Date verwenden oder zu java.time.LocalDate wechseln?

74

Edit: Nun, anscheinend war es zu meinungsbasiert, also lass mich versuchen, es genauer umzuformulieren -

Gibt es klare Vorbehalte oder Nachteile bei der Verwendung von LocalDate, LocalTime usw. in einem Java-Code, für den keine Abwärtskompatibilität erforderlich ist, und wenn ja, welche?

Ich suche nach Dingen wie "Aktuelle EE-Bibliotheken X und Y funktionieren mit LocalDate nicht richtig" oder "Dieses sehr nützliche Muster ist mit LocalTime gebrochen" und so weiter.


(hier ist die ursprüngliche Frage als Referenz)

Mit Java 8 wird eine neue Zeit-API eingeführt, nämlich java.time.LocalDate usw., aber java.util.Date wird nicht als veraltet markiert.

Ich schreibe ein neues Projekt, das nicht abwärtskompatibel sein muss. Sollte ich nur LocalDate, LocalDateTime usw. verwenden? Gibt es irgendwelche Nachteile bei der Verwendung dieser neuen API im Gegensatz zum guten alten java.util.Date?

Insbesondere - ich werde hauptsächlich mit JDBC arbeiten. Nach dem, was ich gesehen habe, geht JDBC gut mit java.util.Date um. Ist es auch für LocalDate geeignet?

Die Suche ergab viele Websites, auf denen erklärt wurde, wie von einem Format in das andere konvertiert werden soll, aber keine endgültige Antwort darauf, ob neuer Code die alte API verwenden sollte.

Vielen Dank.

Itai
quelle
10
good old java.util.Date- Es ist alt, aber nicht gut. Neuer Code sollte eine neue API verwenden.
Iłya Bursov
7
Es gibt einen Grund, warum eine völlig neue Datums-API erstellt wurde. Wenn Sie ein Greenfield-Projekt haben, verwenden Sie die in Java 8 eingeführte API.
Jeroen Vannevel
1
Bitte verwenden Sie die neue API. :-P
Paul Vargas
3
Java ist misstrauisch, die Annotation @Deprecated für Dinge zu verwenden, die schlecht sind, aber nicht gelöscht werden.
Louis Wasserman
3
Die Oracle-eigene Dokumentation gibt drei Hauptgründe für die Ablehnung einer API an: "Sie ist unsicher, fehlerhaft oder äußerst ineffizient. Sie wird in einer zukünftigen Version nicht mehr verwendet. Sie fördert schlechte Codierungspraktiken." Ob diese für java.util.Date gelten, ist möglicherweise Ansichtssache.
MarsAtomic

Antworten:

54

Trotz des Namens kann java.util.Date zum Speichern von Datum und Uhrzeit verwendet werden (es speichert den seit der Epoche versetzten UTC-Millisekundenversatz).

Ich würde die neue API definitiv wegen größerer Funktionen verwenden:

  • Einfacheres Formatieren / Parsen. Die API verfügt über eigene Format- / Analysemethoden
  • Die API enthält Additions- / Subtraktionsoperationen (minus Minuten, plus Tage usw.)

Keine der oben genannten Optionen ist auf java.util.Date verfügbar

Altes Datum kann auch wie folgt in LocalDateTime konvertiert werden:

Date oldDate = ...
LocalDateTime newDateTime = 
  LocalDateTime.from(Instant.ofEpochMilli(oldDate.getTime()));
Gerrytan
quelle
2
Nach Ihrer Meinung ist es also an der Zeit, das alte Datum überhaupt zu verwerfen?
Shedom Wei
@ShedomWei Alles hängt von Ihren Projektanforderungen ab. OP entschied sich, bei altem Datum zu bleiben, weil "anscheinend MySQL Connector J Java 8 nicht unterstützt" (Itai 3. März 15 um 0:40).
Stephan
15

Ich füge zur richtigen Antwort von Ole VV hinzu

JDBC 4.2

Insbesondere - ich werde hauptsächlich mit JDBC arbeiten.

JDBC 4.2 hat Unterstützung für den Austausch von java.time- Objekten mit der Datenbank hinzugefügt . Siehe die PreparedStatement::setObjectund ResultSet::getObjectMethoden.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;
myPreparedStatement.setObject( … , today ) ;

Abruf.

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

Aus Gründen , die mir zu entkommen, die JDBC - Spezifikation ist nicht erforderlich Unterstützung für die beiden am häufigsten verwendeten Klassen: Instantund ZonedDateTime. Ihre Datenbank und Ihr JDBC-Treiber unterstützen diese möglicherweise nicht.

Wenn nicht, können Sie leicht konvertieren. Beginnen Sie mit der OffsetDateTimein JDBC erforderlichen Unterstützung.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

Um diesen Moment durch die Wanduhrzeit zu sehen, die von Personen einer bestimmten Region (einer Zeitzone) verwendet wird, wenden Sie a ZoneIdan, um ein ZonedDateTimeObjekt zu erhalten.

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant() ;

Um sich auf UTC einzustellen, extrahieren Sie eine Instant. An Instantist per Definition immer in UTC.

Instant instant = odt.toInstant() ;

Sie können auch umgekehrt konvertieren, um in eine Datenbank zu schreiben.

myPreparedStatement.setObject( … , zdt.toOffsetDateTime() ;  // Converting from `ZonedDateTime` to `OffsetDateTime`. Same moment, same point on the timeline, different wall-clock time.

…und:

myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ;  // Converting from `Instant` to `OffsetDateTime`. Same moment, same point on the timeline, and even the same offset. `OffsetDateTime` is a more flexible class with abilities such as (a) applying various offsets and (b) flexible formatting when generating text, while `Instant` is meant to be a more basic building-block class. 

Beachten Sie die Namenskonvention in verwendet java.time : at, from, to, with, und so weiter.

Tabelle der Datums- und Uhrzeittypen in Java (sowohl modern als auch Legacy) und in Standard-SQL.


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

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

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

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 Zeichenfolgen, 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
1

Java 8 und höher: keine Sorge

Nein, es gibt keinen Grund, warum Sie java.time, die moderne Java-API für Datum und Uhrzeit, nicht verwenden möchten, wenn Sie Java 8 oder höher verwenden (wo es integriert ist).

Das einzige, was man kurz betrachten kann, ist das, das Sie bereits ausgeschlossen haben.

Ich schreibe ein neues Projekt, das nicht abwärtskompatibel sein muss.

Und selbst aus Gründen der Abwärtskompatibilität können Sie java.time sicher verwenden, da Konvertierungsmethoden in die alten Klassen von Java 8 integriert sind.

Java 6 und 7: wiegen

Wenn Sie mit Java 6 oder 7 arbeiten, müssen Sie den ThreeTen-Backport für java.time verwenden, der für Android unter API Level 26 in ThreeTenABP weiter angepasst ist . Wenn Sie nur sehr wenig, sehr einfache Datums- und Zeitarbeit leisten und die Vorwärtskompatibilität irgendwie kein Problem darstellt, können Sie überlegen, ob sich die externe Abhängigkeit lohnt. Bitte berücksichtigen Sie, dass Ihre externe Abhängigkeit nur ein Backport dessen ist, was in Java 8 und höher integriert ist, also absolut solide, und dass Sie sie daher nur benötigen, bis Sie auf Java 8 oder höher migrieren. Zu diesem Zeitpunkt können Sie Ihre Importe ändern, erneut testen und den Backport entfernen.

Ihre Beispiele für denkbare Verbindlichkeiten

Aktuelle EE-Bibliotheken X und Y funktionieren mit LocalDate nicht richtig

Es gibt einige Beispiele dafür, auch Bibliotheksklassen im JDK. Meine Wahl wäre, java.time in meinem eigenen Code zu verwenden und erst kurz vor dem Aufruf in die API zu konvertieren, die noch keinen java.time-Typ akzeptiert. Und umgekehrt, wenn ich eine Instanz einer veralteten Klasse von der API erhalte, konvertieren Sie sie als erstes und verwenden Sie für den Rest java.time.

Dieses sehr nützliche Muster wird mit LocalTime gebrochen

Ich kenne kein solches Muster. Im Gegenteil, java.time verwendet im Gegensatz zu den meisten alten Klassen unveränderliche Muster und Factory-Methoden .

Ole VV
quelle