Warum ist der Date-Konstruktor veraltet und was verwende ich stattdessen?
Lesezeit: 6 Minuten
Schiss
Ich komme aus der C#-Welt, bin also noch nicht allzu erfahren mit Java. Das wurde mir gerade von Eclipse mitgeteilt Date wurde verworfen:
Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));
Warum? Und was (insbesondere in Fällen wie oben) sollte stattdessen verwendet werden?
Ich erlebe eine ähnliche Lernkurve und gehe auch von C# zu Java. Die andere Sache, die mich gestört hat, ist, dass der Monat des Jahres ein 0-basiertes System ist (0 bis 11, wobei Jan. = 0 und Dez. = 11), aber die Tage des Monats sind 1-basiert (1 bis 31). Kopf hoch!
– Paul Sasik
15. April 2011 um 13:36 Uhr
@Paul Sasik, ja, aber es gibt zum Beispiel eine Calendar.JANUARY-Konstante und eine für jeden Monat
– Diago
15. April 2011 um 14:07 Uhr
@PaulSasik lol. Ja, dummes Java. Musste von C # zu Java wechseln und OMG die Schmerzen und das Elend.
– cbmeeks
22. März 2013 um 13:56 Uhr
mögliches Duplikat von Warum wurden die meisten java.util.Date-Methoden als veraltet markiert?
– Thomas
26. November 2013 um 8:00 Uhr
Die bissigen “lol”-Bemerkungen über Java von C#-Leuten Mich lachen, weil .Net seine anständige Datums-Zeit-Bibliothek hat (Noda-Zeit) aus einer Portierung der exzellenten Java-Bibliothek Joda-Zeit.
– Basilikum Bourque
6. Februar 2014 um 8:48 Uhr
BüffelBüffel
Der java.util.Date class ist nicht wirklich veraltet, nur dieser Konstruktor ist zusammen mit einigen anderen Konstruktoren/Methoden veraltet. Es wurde verworfen, weil diese Art der Verwendung nicht gut mit der Internationalisierung funktioniert. Der Calendar Klasse sollte stattdessen verwendet werden:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();
Wenn Sie sagen “funktioniert nicht gut mit Internationalisierung”, meinen Sie, dass Sie für Datum keine Zeitzone zuweisen können? Danke
– Eintauchen in
1. Dezember 2015 um 5:55 Uhr
Was Date hat einen String geparst, also müssen wir jetzt stattdessen einen String substringen, der das Jahr, den Monat und den Tag enthält? Scheint eine Menge zusätzlicher Aufwand für etwas zu sein, das in den meisten Fällen keine so komplexe Logik und Methoden benötigt, die hinzugefügt werden müssen.
– G_V
6. März 2017 um 8:39 Uhr
Nur um hinzuzufügen, wird die Standardzeitzone berücksichtigt. Wenn wir eine andere Zeitzone angeben möchten, können wir verwenden Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(<timezone id>));
– Vikas Prasad
17. März 2017 um 16:45 Uhr
“Stattdessen sollte die Calendar-Klasse verwendet werden” – Für Java 8 und höher ist die java.time.* Klassen sind die bessere Option … wenn Sie Ihren Code ändern.
– Stefan C
30. Mai 2018 um 6:15 Uhr
Basil Bourque
tl;dr
LocalDate.of( 1985 , 1 , 1 )
…oder…
LocalDate.of( 1985 , Month.JANUARY , 1 )
Einzelheiten
Der java.util.Date, java.util.CalendarUnd java.text.SimpleDateFormat Klassen wurden zu schnell überstürzt, als Java zum ersten Mal gestartet und weiterentwickelt wurde. Die Klassen waren nicht gut konzipiert oder implementiert. Es wurden Verbesserungen versucht, daher die Verwerfungen, die Sie gefunden haben. Leider sind die Verbesserungsversuche weitgehend gescheitert. Du solltest Vermeiden Sie diese Klassen insgesamt. Sie werden in Java 8 durch neue Klassen ersetzt.
Probleme in Ihrem Code
Ein java.util.Date hat sowohl einen Datums- als auch einen Zeitteil. Sie haben den Zeitabschnitt in Ihrem Code ignoriert. Die Date-Klasse nimmt also den Anfang des Tages, wie er durch die Standardzeitzone Ihrer JVM definiert ist, und wendet diese Zeit auf das Date-Objekt an. Die Ergebnisse Ihres Codes variieren also je nachdem, auf welchem Computer er ausgeführt wird oder welche Zeitzone eingestellt ist. Wahrscheinlich nicht das, was Sie wollen.
Wenn Sie nur das Datum ohne den Zeitteil möchten, wie z. B. für ein Geburtsdatum, möchten Sie möglicherweise kein a verwenden Date Objekt. Möglicherweise möchten Sie nur eine Zeichenfolge des Datums in speichern ISO 8601 Format von YYYY-MM-DD. Oder verwenden Sie eine LocalDate Objekt von Joda-Time (siehe unten).
Joda-Zeit
Das erste, was Sie in Java lernen sollten: Vermeiden Sie die notorisch problematischen java.util.Date- und java.util.Calendar-Klassen gebündelt mit Java.
Wie in der Antwort von user3277382 richtig angegeben, verwenden Sie entweder Joda-Zeit oder das neue java.time.*-Paket bei Java8.
In diesem Fall ist der Code für java.time ist nahezu identisch mit der von Joda-Zeit.
Wir bekommen eine Zeitzone (ZoneId) und erstellen Sie ein dieser Zeitzone zugewiesenes Datum-Uhrzeit-Objekt (ZonedDateTime). Dann mit der Unveränderliche Objekte Muster, erstellen wir neue Datums-Zeiten basierend auf demselben Zeitpunkt des alten Objekts (Anzahl der Nanosekunden seitdem Epoche), aber einer anderen Zeitzone zugewiesen. Zuletzt bekommen wir a LocalDate die keine Tageszeit oder Zeitzone hat, beachten Sie jedoch, dass die Zeitzone bei der Bestimmung dieses Datums gilt (ein neuer Tag dämmert früher in Oslo als in New York Zum Beispiel).
Weitere Informationen finden Sie unter Oracle-Tutorial. Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Spezifikation ist JSR310.
Sie dürfen umtauschen java.time Objekte direkt mit Ihrer Datenbank. Benutze einen JDBC-Treiber gemäß JDBC 4.2 oder später. Keine Notwendigkeit für Saiten, keine Notwendigkeit für java.sql.* Klassen. Unterstützung für Hibernate 5 und JPA 2.2 java.time.
Spätere Versionen von Android (26+) bündeln Implementierungen der java.time Klassen.
Für frühere Android-Versionen (<26) ermöglichen die neuesten Android-Tools einen Prozess namens API-Entzuckerung bieten ein Teilmenge der java.time Funktionen, die ursprünglich nicht in Android integriert waren.
Wenn die Entzuckerung nicht das bietet, was Sie brauchen, die ThreeTenABP Projekt passt ThreeTen-Backport (oben erwähnt) auf Android. Sehen Wie benutzt man ThreeTenABP….
Requisiten, um die eigentliche Ursache zu erwähnen und alle verfügbaren Alternativen abzudecken.
– mabi
11. April 2016 um 13:52 Uhr
Dies ist die richtige Antwort und die Kalenderklasse sollte vermieden werden. ThreeTen ist die beste Option
– Ameise2009
16. November 2019 um 14:21 Uhr
@Basil Bourque Sie erwähnen spätere Versionen von Android-Bundle-Implementierungen von java.time-Klassen. Kannst du genauer sagen welche Versionen? Ich versuche, alten Datums- und Kalendercode für eine Android-App zu ersetzen, bin mir aber nicht sicher, wo ich anfangen soll.
– AJW
22. November 2021 um 3:37 Uhr
@AJW Diese Informationen sind bereits im letzten Abschnitt der Antwort “Über java.time” enthalten, die ich gerade aktualisiert habe.
– Basilikum Bourque
22. November 2021 um 6:10 Uhr
Sehr gut, danke für das Update.
– AJW
22. November 2021 um 15:17 Uhr
Ruben
Das spezifische Date Konstruktor ist veraltet, und Calendar sollte stattdessen verwendet werden. Der JavaDoc für Datum beschreibt, welche Konstruktoren veraltet sind und wie sie mit a ersetzt werden Calendar.
Der Kalender erfordert ein zusätzliches Objekt und etwa 8 Zeilen mehr Code, um dasselbe zu tun, nämlich ein Date-Objekt zu erstellen, von dem, was ich sagen kann. Es ist verwirrend und erscheint unnötig, wenn Sie nur ein Datum und keine zeitzonenangepasste Variable benötigen.
Ich bin auf diese Frage als Duplikat einer neueren Frage gestoßen, in der gefragt wurde, wie man a erhält Date in einem bestimmten Jahr, Monat und Tag war.
Die Antworten hier bisher sagen, um die zu verwenden Calendar Klasse, und das galt, bis Java 8 herauskam. Aber ab Java 8 ist dies standardmäßig so:
LocalDate localDate = LocalDate.of(1985, 1, 1);
Und dann, wenn Sie wirklich wirklich brauchen java.util.Datekönnen Sie die Vorschläge in dieser Frage verwenden.
Ein Grund dafür, dass der Konstruktor veraltet ist, ist, dass die Bedeutung des year-Parameters nicht Ihren Erwartungen entspricht. Der Javadoc sagt:
Ab JDK-Version 1.1 ersetzt durch Calendar.set(year + 1900, month, date).
Beachten Sie, dass das Feld year die Anzahl der Jahre seither ist 1900, sodass Ihr Beispielcode höchstwahrscheinlich nicht das tut, was Sie erwarten. Und das ist der Punkt.
Im Allgemeinen ist die Date Die API unterstützt nur den modernen westlichen Kalender, hat eigenwillig spezifizierte Komponenten und verhält sich inkonsistent, wenn Sie Felder festlegen.
Der Calendar Und GregorianCalendar APIs sind besser als Date, und die Joda-Time-APIs von Drittanbietern wurden allgemein als die besten angesehen. In Java 8 führten sie die java.time Pakete, und diese sind jetzt die empfohlene Alternative.
Diese Lösung funktioniert hervorragend, außer dass sie keine Nullzeit für Stunden-Minuten-Sekunden-Millisekunden verwendet, wie es bei new Date(year, month, day) der Fall war. Wir brauchen also so etwas wie: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(Jahr + 1900, Monat, Datum); Datum dateRepresentation = cal.getTime();
– Joel Richard Koett
3. Mai 2019 um 23:02 Uhr
nbäche
Bitte beachte, dass Calendar.getTime() ist nicht deterministisch in dem Sinne, dass die Tageszeit Teil ist standardmäßig auf die aktuelle Zeit eingestellt.
Versuchen Sie zur Reproduktion, den folgenden Code ein paar Mal auszuführen:
Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());
Ausgabe zB:
Sun Mar 07 10:46:21 CET 2010
Das Ausführen des exakt gleichen Codes ein paar Minuten später ergibt:
Sun Mar 07 10:57:51 CET 2010
Also, während set() zwingt entsprechende Felder zu korrekten Werten, es verliert Systemzeit für die anderen Felder. (Oben getestet mit Sun jdk6 & jdk7)
Diese Lösung funktioniert hervorragend, außer dass sie keine Nullzeit für Stunden-Minuten-Sekunden-Millisekunden verwendet, wie es bei new Date(year, month, day) der Fall war. Wir brauchen also so etwas wie: Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(Jahr + 1900, Monat, Datum); Datum dateRepresentation = cal.getTime();
– Joel Richard Koett
3. Mai 2019 um 23:02 Uhr
Rob W
Date selbst ist nicht veraltet. Es ist nur eine Menge seiner Methoden. Siehe hier für Details.
Ich erlebe eine ähnliche Lernkurve und gehe auch von C# zu Java. Die andere Sache, die mich gestört hat, ist, dass der Monat des Jahres ein 0-basiertes System ist (0 bis 11, wobei Jan. = 0 und Dez. = 11), aber die Tage des Monats sind 1-basiert (1 bis 31). Kopf hoch!
– Paul Sasik
15. April 2011 um 13:36 Uhr
@Paul Sasik, ja, aber es gibt zum Beispiel eine Calendar.JANUARY-Konstante und eine für jeden Monat
– Diago
15. April 2011 um 14:07 Uhr
@PaulSasik lol. Ja, dummes Java. Musste von C # zu Java wechseln und OMG die Schmerzen und das Elend.
– cbmeeks
22. März 2013 um 13:56 Uhr
mögliches Duplikat von Warum wurden die meisten java.util.Date-Methoden als veraltet markiert?
– Thomas
26. November 2013 um 8:00 Uhr
Die bissigen “lol”-Bemerkungen über Java von C#-Leuten Mich lachen, weil .Net seine anständige Datums-Zeit-Bibliothek hat (Noda-Zeit) aus einer Portierung der exzellenten Java-Bibliothek Joda-Zeit.
– Basilikum Bourque
6. Februar 2014 um 8:48 Uhr