Java Date vs Calendar


364

Könnte jemand bitte die aktuellen "Best Practice" Dateund CalendarTypen beraten .

Wenn neuen Code zu schreiben, ist es am besten, immer zu bevorzugen Calendarüber Date, oder gibt es Situationen , in denen Dateist der geeignetere Datentyp?



2
Zu Ihrer Information, die störenden alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe, durch die verdrängte java.time Klassen. Ein Großteil der Funktionen von java.time wird im ThreeTen-Backport- Projekt auf Java 6 und Java 7 zurückportiert . Weiter angepasst für frühere Android im ThreeTenABP- Projekt. Siehe Verwendung von ThreeTenABP… .
Basil Bourque

2
Zu Ihrer Information , das Joda-Time- Projekt (in einem anderen Kommentar erwähnt) befindet sich jetzt im Wartungsmodus , wobei das Team die Migration zu den Klassen java.time empfiehlt . Siehe Tutorial von Oracle .
Basil Bourque

Antworten:


377

Datum ist eine einfachere Klasse und wird hauptsächlich aus Gründen der Abwärtskompatibilität verwendet. Wenn Sie bestimmte Daten festlegen oder Datumsarithmetik durchführen müssen, verwenden Sie einen Kalender. Kalender übernehmen auch die Lokalisierung. Die vorherigen Datumsmanipulationsfunktionen von Date sind seitdem veraltet.

Persönlich neige ich dazu, entweder die Zeit in Millisekunden als Long (oder Long, je nach Bedarf) oder als Kalender zu verwenden, wenn ich die Wahl habe.

Sowohl Datum als auch Kalender sind veränderbar, was bei Verwendung in einer API zu Problemen führen kann.


5
Zu Ihrer Information, die furchtbar lästig alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 und höher. Siehe Tutorial von Oracle .
Basil Bourque

67

Der beste Weg für neuen Code (wenn Ihre Richtlinie Code von Drittanbietern zulässt) ist die Verwendung der Joda Time-Bibliothek .

Beides, Datum als auch Kalender haben so viele Designprobleme, dass beide keine gute Lösung für neuen Code sind.


7
Ich stimme dem Vorschlag zu, Joda Time zu verwenden. Es ist einfacher zu bedienen und zu verstehen und bietet viel mehr Funktionen, die Sie verwenden können.
Jeroen van Bergen

30
Eine Diskussion darüber, ob Sie Joda Time verwenden oder sich an Standard-JDK-Klassen halten sollen, finden Sie unter stackoverflow.com/questions/589870/…
Jonik

3
Ich weiß nicht, ob es Abstimmungen verdient, aber es beantwortet die Frage nicht. Könnte als Kommentar einfach besser sein.
IcedDante

7
Weil es um die Verwendung von Datum und Kalender ging, ohne dass eine Bibliothek eines Drittanbieters verwendet wurde, wodurch einem Projekt ein Risiko für die Abhängigkeit eines einzelnen Anbieters hinzugefügt wird.
Archimedes Trajano

3
Dies war der "beste Weg", bis das Paket java.time mit Java 8 verfügbar gemacht wurde.
DaBlick

58
  • Dateund Calendarsind wirklich das gleiche grundlegende Konzept (beide repräsentieren einen Zeitpunkt und sind Wrapper um einen zugrunde liegenden longWert).

  • Man könnte argumentieren, dass dies Calendarsogar noch mehr kaputtDate ist als es ist, da es konkrete Fakten über Dinge wie Wochentag und Tageszeit zu bieten scheint, während sich timeZoneder Beton in Pudding verwandelt , wenn Sie seine Eigenschaft ändern ! Aus diesem Grund sind keine Objekte als Speicher für Jahr, Monat, Tag oder Uhrzeit wirklich nützlich .

  • Verwenden Sie Calendarnur als Taschenrechner , die, wenn gegeben Dateund TimeZoneObjekte, wird für Sie Berechnungen tun. Vermeiden Sie die Verwendung für die Eingabe von Eigenschaften in einer Anwendung.

  • Verwenden Sie SimpleDateFormatzusammen mit TimeZoneund Date, um Anzeigezeichenfolgen zu generieren.

  • Wenn Sie sich abenteuerlustig fühlen, verwenden Sie Joda-Time, obwohl es meiner Meinung nach unnötig kompliziert ist und in Kürze auf jeden Fall von der JSR-310-Datums-API abgelöst wird.

  • Ich habe zuvor geantwortet, dass es nicht schwierig ist, eine eigene YearMonthDayKlasse zu rollen , die Calendarunter der Haube für Datumsberechnungen verwendet wird. Ich wurde für den Vorschlag abgelehnt, aber ich glaube immer noch, dass er gültig ist, da Joda-Time (und JSR-310 ) für die meisten Anwendungsfälle wirklich so kompliziert sind.


1
Gibt es einen Zeitrahmen für JSR310? Es sollte in Java 7 sein, aber ich glaube, das ist jetzt nicht der Fall.
Brian Agnew

@Brian - auf dieser Mailingliste ist es sicherlich sehr ruhig geworden!
oxbow_lakes

Nur überprüfen, es ist inaktiv gegangen, was bedeutet, dass sie seit 18 Monaten keinen Meilensteinentwurf veröffentlicht haben :-(
Brian Agnew

Der letzte Kommentar auf der Mailingliste stammt aus dem Juli und von Stephen, daher tickt das Projekt wahrscheinlich immer noch weg
oxbow_lakes

Einverstanden. Wenn Sie wissen, wie Sie Datum sicher als unveränderliches Objekt und Kalender zum Bearbeiten von Daten verwenden, sollten die meisten Personen sicher sein. Seien Sie vorsichtig, wenn Sie SimpleDateFormat in Multithread-Code verwenden.
cwash

25

Datum ist am besten zum Speichern eines Datumsobjekts geeignet. Es ist das Beharrliche, das Serialisierte ...

Der Kalender eignet sich am besten zum Bearbeiten von Daten.

Hinweis: Manchmal bevorzugen wir auch java.lang.Long gegenüber Date, da Date veränderlich und daher nicht threadsicher ist. Verwenden Sie für ein Date-Objekt setTime () und getTime (), um zwischen den beiden zu wechseln. Zum Beispiel ein konstantes Datum in der Anwendung (Beispiele: die Null 1970/01/01 oder eine anwendbare END_OF_TIME, die Sie auf 2099/12/31 festgelegt haben; diese sind sehr nützlich, um insbesondere Nullwerte als Start- und Endzeit zu ersetzen wenn Sie sie in der Datenbank beibehalten, da SQL mit Nullen so eigenartig ist).


Ich nehme an, Sie nehmen über das Unveränderlichejava.lang.Long
pjp

17

Ich benutze normalerweise Datum, wenn möglich. Obwohl es veränderlich ist, sind die Mutatoren tatsächlich veraltet. Am Ende wird im Grunde ein Long umbrochen, der das Datum / die Uhrzeit darstellt. Umgekehrt würde ich Kalender verwenden, wenn ich die Werte manipulieren müsste.

Sie können sich das so vorstellen: Sie verwenden StringBuffer nur, wenn Sie Strings benötigen, die Sie einfach bearbeiten und dann mit der toString () -Methode in Strings konvertieren können. Ebenso verwende ich Kalender nur, wenn ich zeitliche Daten bearbeiten muss.

Für bewährte Methoden verwende ich unveränderliche Objekte so oft wie möglich außerhalb des Domänenmodells . Es verringert die Wahrscheinlichkeit von Nebenwirkungen erheblich und wird vom Compiler anstelle eines JUnit-Tests für Sie durchgeführt. Sie verwenden diese Technik, indem Sie ein privates Finale erstellen Endfelder in Ihrer Klasse .

Und zurück zur StringBuffer-Analogie. Hier ist ein Code, der Ihnen zeigt, wie Sie zwischen Kalender und Datum konvertieren

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);

Ja, unveränderliche Objekte sind für die Arbeit mit Datum und Uhrzeit sinnvoll. Die java.time- Klassen, die das Muster der unveränderlichen Objekte ersetzt Date/ Calendarverwendet haben.
Basil Bourque

Das mag wahr sein, aber nicht im Jahr 2010.
Archimedes Trajano

Ja. Aber es gibt jetzt Tausende von Menschen, die diese Seite lesen , bisher über 150.000. Mein Kommentar ist eine Notiz an sie, keine Kritik an Ihnen.
Basil Bourque

Ich weiß, deshalb habe ich die andere Antwort positiv bewertet. Es gibt jedoch immer noch einige Menschen, die unter den älteren JDKs leiden müssen, die auch die obige Antwort benötigen.
Archimedes Trajano

1
Für Java 6 & 7 haben wir das ThreeTen-Backport- Projekt. Dies bringt den größten Teil der java.time- Funktionalität mit praktisch derselben API. Es ist also nicht nötig, jemals diese schrecklichen alten Datums- / Zeitklassen zu verwenden.
Basil Bourque

15

Dates sollte als unveränderlicher Zeitpunkt verwendet werden; Calendars sind veränderbar und können weitergegeben und geändert werden, wenn Sie mit anderen Klassen zusammenarbeiten müssen, um ein endgültiges Datum zu ermitteln. Betrachten Sie sie analog zu StringundStringBuilder Sie werden verstehen, wie ich denke, dass sie verwendet werden sollten.

(Und ja, ich weiß, dass Date technisch nicht unveränderlich ist, aber die Absicht ist, dass es nicht veränderlich sein sollte, und wenn nichts die veralteten Methoden aufruft, ist es so.)


Ja, unveränderliche Objekte sind für die Arbeit mit Datum und Uhrzeit sinnvoll. Die java.time- Klassen, die das Muster der unveränderlichen Objekte ersetzt Date/ Calendarverwendet haben. Insbesondere Instantersetzt java.util.Dateund ZonedDateTimeersetzt Calendar/ GregorianCalendar.
Basil Bourque

15

tl; dr

beraten die aktuellen "Best Practice" um DateundCalendar

am besten ist es immer zu bevorzugen CalendarüberDate

Vermeiden Sie diese Legacy-Klassen vollständig. Verwenden Sie stattdessen java.time- Klassen.

  • Verwenden Sie für einen Moment in UTC (das moderne Äquivalent vonInstant
    Date )
  • Verwenden Sie für einen Moment in einer bestimmten Zeitzone (das moderne Äquivalent von )ZonedDateTime
    GregorianCalendar
  • Verwenden Sie für einen Moment in einem bestimmten Versatz von UTCOffsetDateTime
    (kein Äquivalent in Legacy-Klassen).
  • Verwenden Sie für eine Datums- und Uhrzeitangabe (keinen Moment) mit unbekannter Zeitzone oder Versatz (kein Äquivalent in Legacy-Klassen).LocalDateTime

Tabelle aller Datums- und Uhrzeittypen in Java, sowohl moderne als auch ältere

Einzelheiten

Die Antwort von Ortomala Lokni schlägt zu Recht vor, die modernen java.time- Klassen anstelle der problematischen alten alten Datums- / Uhrzeitklassen zu verwenden ( Date,Calendar usw.). Aber diese Antwort schlägt die falsche Klasse als gleichwertig vor (siehe meinen Kommentar zu dieser Antwort).

Mit java.time

Die java.time-Klassen sind eine enorme Verbesserung gegenüber den bisherigen Datums- und Uhrzeitklassen sowie dem Unterschied zwischen Tag und Nacht. Die alten Klassen sind schlecht gestaltet, verwirrend und mühsam. Sie sollten die alten Klassen nach Möglichkeit meiden. Wenn Sie jedoch in / aus dem alten / neuen konvertieren müssen, können Sie dies tun, indem Sie neue Methoden aufrufen, die dem alten hinzufügen Klassen werden.

Weitere Informationen zur Konvertierung finden Sie in meiner Antwort und in meinem übersichtlichen Diagramm zu einer anderen Frage: Konvertieren Sie java.util.Date in welchen Typ "java.time"?.

Searching Stack Overflow bietet viele hundert Beispielfragen und -antworten zur Verwendung von java.time. Aber hier ist eine kurze Zusammenfassung.

Instant

Holen Sie sich den aktuellen Moment mit einem Instant. Die InstantKlasse repräsentiert einen Moment auf der Zeitachse in UTC mit einer Auflösung von Nanosekunden (bis zu neun (9) Stellen eines Dezimalbruchs).

Instant instant = Instant.now();

ZonedDateTime

Wenden Sie eine Zeitzone ( ) an, um das gleiche simultane Moment durch die Linse der Wanduhrzeit einer bestimmten Region zu sehen .ZoneIdZonedDateTime

Zeitzone

Geben Sie einen richtigen Zeitzonennamen im Format continent/region, wie zum Beispiel America/Montreal, Africa/Casablancaoder Pacific/Auckland. Verwenden Sie niemals die Abkürzung für 3-4 Buchstaben, wie z. B. ESToder, ISTda es sich nicht um echte Zeitzonen handelt, die nicht standardisiert und nicht einmal eindeutig (!) Sind.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

Offset

Eine Zeitzone ist die Änderungshistorie einer Region in Bezug auf den Versatz von UTC . Aber manchmal erhalten Sie nur einen Versatz ohne die volle Zone. Verwenden Sie in diesem Fall die OffsetDateTimeKlasse.

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

Die Verwendung einer Zeitzone ist der Verwendung eines bloßen Versatzes vorzuziehen.

LocalDateTime

Das "Lokal" in den Local…Klassen bedeutet " beliebig" Ort, keinen bestimmten Ort. Der Name kann also kontraintuitiv sein.

LocalDateTime, LocalDateUnd LocalTimefehlen absichtlich keine Informationen über Offset- oder Zeitzone. Sie stellen also keine tatsächlichen Momente dar, sie sind keine Punkte auf der Zeitachse. Verwenden Sie im Zweifelsfall oder in der Verwirrung ZonedDateTimeeher alsLocalDateTime . Search Stack Overflow für viel mehr Diskussion.

Saiten

Kombinieren Sie Datums- und Uhrzeitobjekte nicht mit Zeichenfolgen, die ihren Wert darstellen. Sie können eine Zeichenfolge analysieren, um ein Datums- / Uhrzeitobjekt abzurufen, und Sie können eine Zeichenfolge aus einem Datums- / Uhrzeitobjekt generieren. Die Zeichenfolge ist jedoch niemals die Datums- und Uhrzeit selbst.

Erfahren Sie mehr über die Standardformate ISO 8601 , die standardmäßig in den Klassen java.time verwendet werden.


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

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

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

Wenn Sie einen JDBC-Treiber verwenden, der mit JDBC 4.2 oder höher kompatibel ist , können Sie java.time- Objekte direkt mit Ihrer Datenbank austauschen . Keine Notwendigkeit für Strings oder java.sql. * Klassen.

Woher bekomme ich die java.time-Klassen?

Tabelle, welche java.time-Bibliothek mit welcher Java- oder Android-Version verwendet werden soll

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 .


10

Mit Java 8 das neue Paket java.time verwendet werden.

Objekte sind unveränderlich, Zeitzonen und Sommerzeit werden berücksichtigt.

Sie können ein ZonedDateTimeObjekt aus einem alten java.util.DateObjekt wie folgt erstellen :

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());

Gut, die java.time-Klassen vorzuschlagen. Aber schlecht vorzuschlagen LocalDateTime. Diese Klasse verliert absichtlich alle Informationen über den Versatz von UTC und die Zeitzone. Diese Klasse ist also nicht wie Datein UTC gleichwertig und Calendarhat eine zugewiesene Zeitzone. Siehe meine Antwort und das übersichtliche Diagramm in eine andere Frage: Konvertieren Sie java.util.Date in welchen Typ "java.time"? .
Basil Bourque

9

Ich befürworte immer die Joda-Zeit . Hier ist der Grund.

  1. Die API ist konsistent und intuitiv. Im Gegensatz zu den APIs java.util.Date/Calendar
  2. Im Gegensatz zu java.text.SimpleDateFormat usw. treten keine Threading-Probleme auf . (Ich habe zahlreiche Client-Probleme festgestellt, die darauf zurückzuführen sind, dass die Standardformatierung von Datum und Uhrzeit nicht threadsicher ist.)
  3. Dies ist die Grundlage für die neuen Java-APIs für Datum und Uhrzeit ( JSR310 , geplant für Java 8. Sie verwenden also APIs, die zu zentralen Java-APIs werden.

BEARBEITEN: Die mit Java 8 eingeführten Java-Datums- / Zeitklassen sind jetzt die bevorzugte Lösung, wenn Sie auf Java 8 migrieren können


3
Als ich das letzte Mal nachgesehen habe, sahen JODA und JSR-310 sehr unterschiedlich aus, auch wenn beide von Stephen Colebourne geschrieben wurden. Das heißt, JODA würde Sie in die Komplexität der Datums- / Zeitprobleme einführen, die JSR-310 ebenfalls löst
oxbow_lakes

2
Weil es um die Verwendung von Datum und Kalender ging, ohne dass eine Bibliothek eines Drittanbieters verwendet wurde, wodurch einem Projekt ein Risiko für die Abhängigkeit eines einzelnen Anbieters hinzugefügt wird.
Archimedes Trajano

2
Ich behaupte, die beste Vorgehensweise ist einfach, diese Klassen nicht zu verwenden
Brian Agnew

3
Angesichts der bekannten Probleme mit den Klassen java.util.Date und Calendar erscheint es mir angemessen und verantwortlich, Joda-Time (oder JSR 310) vorzuschlagen. Wir sprechen nicht über Geschmack oder ästhetischen Stil. Wenn jemand fragte, ob er das rote oder das silberne Auto nehmen sollte und ich wusste, dass das rote Auto einen platten Reifen und das silberne Auto einen kaputten Kühler hatte, sollte ich mir ein Auto aussuchen oder ein Taxi vorschlagen? Die Antwort auf diese Frage sollte heutzutage offensichtlich sein, da sogar Sun / Oracle beschlossen hat, diese Junker zurückzulassen und ein neues Auto zu kaufen: JSR 310: Datums- und Zeit-API.
Basil Bourque

1
Zu Ihrer Information , das Joda-Time- Projekt befindet sich jetzt im Wartungsmodus und empfiehlt die Migration zu den Klassen java.time . Siehe Tutorial von Oracle .
Basil Bourque

8

Ein bisschen spät auf der Party, aber Java hat eine neue Date Time API in JDK 8. Möglicherweise möchten Sie Ihre JDK-Version aktualisieren und den Standard übernehmen. Kein unordentliches Datum / Kalender mehr, keine Gläser von Drittanbietern mehr.


1

Datum sollte neu entwickelt werden. Anstatt eine lange Interger zu sein, sollte es Jahr, Monat, Datum, Stunde, Minute, Sekunde als separate Felder enthalten. Es kann sogar sinnvoll sein, den Kalender und die Zeitzone zu speichern, mit denen dieses Datum verknüpft ist.

In unserem natürlichen Gespräch ist dies eine DateTime, wenn Sie einen Termin am 1. November 2013 um 13:00 Uhr New Yorker Zeit vereinbaren. Es ist KEIN Kalender. So sollten wir uns auch in Java so unterhalten können.

Wenn das Datum als lange Ganzzahl gespeichert ist (von Millisekunden seit dem 1. Januar 1970 oder so), hängt die Berechnung des aktuellen Datums vom Kalender ab. Unterschiedliche Kalender geben unterschiedliche Daten an. Dies ist aus der Perspektive einer absoluten Zeit (z. B. 1 Billion Sekunden nach dem Urknall). Aber oft brauchen wir auch eine bequeme Art der Konversation, wie ein Objekt, das Jahr, Monat usw. einschließt.

Ich frage mich, ob es in Java neue Fortschritte gibt, um diese beiden Ziele in Einklang zu bringen. Vielleicht ist mein Java-Wissen zu alt.


Die Tatsache, dass Sie denselben Zeitpunkt speichern können, aber unterschiedliche Stunden / Minuten / Tage / Wochen / Jahre / Foo basierend auf unterschiedlichen Kalendersystemen melden, ist eine Stärke und keine Schwäche. Es spiegelt die (komplexe) Realität wider.
ThrawnCA

In der Tat Datewurde neu entwickelt; durch die java.time.InstantKlasse ersetzt. Und Calendar/ GregorianCalendarwurde durch java.time.ZonedDateTimeKlasse ersetzt.
Basil Bourque


0

Ich verwende Kalender, wenn ich bestimmte Vorgänge über die Daten hinweg benötige, z. B. das Verschieben in der Zeit, aber Datum Ich finde es hilfreich, wenn Sie das Datum formatieren müssen, um Ihre Anforderungen anzupassen. Kürzlich habe ich festgestellt, dass das Gebietsschema viele nützliche Vorgänge und Methoden hat Ich benutze gerade das Gebietsschema!


Zu Ihrer Information , die lästigen Calendar& DateKlassen wurden vor Jahren durch die java.time Klassen ersetzt. Keine Notwendigkeit, jemals zu verwenden Dateoder Calendar. Und Localehat nichts mit der Bedeutung von Datums- / Zeitobjekten zu tun. A Localewird nur verwendet, um die menschliche Sprache und die kulturellen Normen anzugeben, die beim Lokalisieren verwendet werden sollen, während Text generiert wird, um den Wert eines Datums- / Uhrzeitobjekts darzustellen.
Basil Bourque
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.