it-swarm.com.de

Java-Datum vs. Kalender

Könnte jemand bitte die aktuellen "Best Practices" rund um die Typen Date und Calendar angeben.

Ist es am besten, beim Schreiben von neuem Code Calendar gegenüber Date zu bevorzugen, oder gibt es Umstände, unter denen Date der geeignetere Datentyp ist?

344
Marty Pitt

Date ist eine einfachere Klasse und ist hauptsächlich aus Gründen der Abwärtskompatibilität vorhanden. Wenn Sie bestimmte Daten festlegen oder Datumsberechnungen durchführen müssen, verwenden Sie einen Kalender. Kalender übernehmen auch die Lokalisierung. Die bisherigen Datumsmanipulationsfunktionen von Date wurden seitdem nicht mehr verwendet.

Persönlich tendiere ich dazu, entweder die Zeit in Millisekunden als Long (oder Long) oder als Kalender zu verwenden, wenn es eine Wahl gibt.

Sowohl Datum als auch Kalender sind veränderbar, was bei der Verwendung von APIs zu Problemen führt.

364
cletus

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

Beide, Date und Calendar , haben so viele Designprobleme, dass beide keine gute Lösung für neuen Code sind.

66
dmeister
  • Date und Calendar sind eigentlich das gleiche Grundkonzept (beide repräsentieren einen Zeitpunkt und sind Wrapper um einen zugrunde liegenden long-Wert). 

  • Man könnte argumentieren, dass Calendar TATSÄCHLICH SOGAR MEHR KAPUTT IST ALS Date, da es scheinbar konkrete Fakten über Dinge wie den Wochentag und die Tageszeit bietet. Wenn Sie jedoch die timeZone-Eigenschaft ändern, verwandelt sich der Beton in blancmange ! Aus diesem Grund sind keine Objekte als Speicher von year-month-day oder time-of-day wirklich nützlich.

  • Verwenden Sie Calendar nur als Taschenrechner, der bei Angabe von Date- und TimeZone-Objekten Berechnungen für Sie ausführt. Vermeiden Sie die Verwendung für die Eingabe von Eigenschaften in einer Anwendung.

  • Verwenden Sie SimpleDateFormat zusammen mit TimeZone und Date, um Anzeigestrings zu generieren.

  • Wenn Sie abenteuerlustig sind, verwenden Sie Joda-Time, obwohl dies IMHO unnötig kompliziert ist und in jedem Fall bald von der JSR-310-Datums-API abgelöst werden soll.

  • Ich habe schon einmal geantwortet, dass es nicht schwierig ist, Ihre eigene YearMonthDay-Klasse zu rollen, die Calendar für Datumsberechnungen unter der Haube verwendet. Ich wurde für den Vorschlag herabgestimmt, glaube aber immer noch, dass er gültig ist, weil Joda-Time (und JSR-310 ) für die meisten Anwendungsfälle wirklich zu kompliziert sind.

53
oxbow_lakes

Das Datum eignet sich am besten zum Speichern eines Datumsobjekts. Es ist das Beständige, das Serialisierte ...

Der Kalender eignet sich am besten für die Bearbeitung von Datumsangaben.

Hinweis: Manchmal bevorzugen wir auch Java.lang.Long over 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: Null 1970/01/01 oder ein anwendbares END_OF_TIME, das Sie auf 2099/12/31 setzen; diese Werte sind sehr nützlich, um Nullwerte als Start- und Endzeit zu ersetzen, insbesondere wenn Sie sie in der Datenbank beibehalten, da SQL mit Nullwerten so eigen ist).

25
KLE

Ich verwende in der Regel Date, wenn möglich. Obwohl sie mutierbar sind, sind die Mutatoren tatsächlich veraltet. Am Ende wird im Wesentlichen eine lange Umhüllung verwendet, die das Datum und die Uhrzeit darstellt. Umgekehrt würde ich Kalender verwenden, wenn ich die Werte manipulieren muss.

Sie können sich das so vorstellen: Sie verwenden StringBuffer nur, wenn Sie Strings benötigen, die Sie leicht bearbeiten und dann mithilfe der toString () - Methode in Strings konvertieren können. Auf dieselbe Weise verwende ich Kalender nur, wenn ich Zeitdaten bearbeiten möchte.

Für die beste Praxis neige ich dazu, unveränderliche Objekte außerhalb des domain-Modells möglichst zu verwenden. Es reduziert die Wahrscheinlichkeit von Nebenwirkungen erheblich und wird vom Compiler für Sie erledigt, anstatt einen JUnit-Test durchzuführen. Sie verwenden diese Technik, indem Sie in Ihrer Klasse private final Felder erstellen.

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);
17

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 erhalten. Betrachten Sie sie als analog zu String und StringBuilder, und Sie werden verstehen, wie ich sie verwenden sollte.

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

15
Andrzej Doyle

tl; dr

beraten Sie die aktuelle "Best Practice" in Bezug auf Date und Calendar

ist es am besten, immer Calendar vor Date zu bevorzugen

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

  • Verwenden Sie für einen Moment in UTC Instant
    (das moderne Äquivalent von Date)
  • Verwenden Sie für einen Moment in einer bestimmten ZeitzoneZonedDateTime
    (das moderne Äquivalent von GregorianCalendar)
  • Verwenden Sie für einen Moment in einem bestimmten Offset-von-UTCOffsetDateTime
    (kein Äquivalent in älteren Klassen)
  • Verwenden Sie LocalDateTime für eine Datumszeit (kein Moment) mit unbekannter Zeitzone oder unbekanntem Versatz
    (kein Äquivalent in älteren Klassen)

Einzelheiten

Die Answer by Ortomala Lokni schlägt zu Recht vor, die modernen Java.time Klassen anstelle der lästigen alten Legacy-Datum-Zeit-Klassen (Date, Calendar usw.). Aber diese Antwort schlägt die falsche Klasse als Äquivalent vor (siehe meinen Kommentar zu dieser Antwort).

Java.time verwenden

Die Java.time-Klassen sind eine enorme Verbesserung gegenüber den alten Datum-Zeit-Klassen, Nacht-und-Tag-Unterschied. 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 und zu den Alten Klassen hinzufügen.

Weitere Informationen zur Konvertierung finden Sie unter meine Antwort und ein schickes Diagramm zu einer anderen Frage, Java.util.Date in welchen Typ "Java.time" konvertieren? .

Das Durchsuchen des Stapelüberlaufs enthält viele hundert Beispielfragen und -antworten zur Verwendung von Java.time. Aber hier ist eine kurze Übersicht.

Instant

Holen Sie sich den aktuellen Moment mit einem Instant. Die Klasse Instant 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

Um zu sehen, dass derselbe Moment gleichzeitig durch die Linse einer bestimmten Region ( Wanduhrzeit läuft, wenden Sie eine Zeitzone an (- ZoneId ) um ein ZonedDateTime zu erhalten.

Zeitzone

Geben Sie ein richtiger Zeitzonenname im Format continent/region An, z. B. America/Montreal , Africa/Casablanca oder Pacific/Auckland. Verwenden Sie niemals die Abkürzung mit 3-4 Buchstaben wie EST oder IST, da diese nicht echte Zeitzonen sind, nicht standardisiert und nicht einmalig (!) .

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

Offset

Bei einer Zeitzone handelt es sich um die Änderungshistorie einer Region in Bezug auf Versatz-von-UTC . Manchmal erhalten Sie jedoch nur einen Versatz ohne die volle Zone. Verwenden Sie in diesem Fall die Klasse OffsetDateTime.

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 "Local" in den Klassen Local… Bedeutet any locality, keine bestimmte Lokalität. Der Name kann also kontraintuitiv sein.

LocalDateTime, LocalDate und LocalTime haben absichtlich keine Informationen über den Versatz oder die Zeitzone. Also stellen sie nicht tatsächliche Momente dar, sie sind nicht Punkte auf der Zeitachse. Verwenden Sie im Zweifelsfall oder bei Unklarheiten ZonedDateTime anstelle von LocalDateTime. Durchsuchen Sie den Stapelüberlauf nach weiteren Informationen.

Streicher

Kombinieren Sie Datum/Uhrzeit-Objekte 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 nie die Datums- und Uhrzeitangabe.

Informieren Sie sich über die Standardformate ISO 8601 , die standardmäßig in den Java.time-Klassen verwendet werden.


About Java.time

Das Java.time Framework ist in Java 8 und höher. Diese Klassen ersetzen das lästige alte Legacy Datum-Zeit-Klassen wie Java.util.Date , Calendar , & SimpleDateFormat .

Das Joda-Time -Projekt, das sich jetzt im Wartungsmodus befindet, rät zur Migration in die Java.time -Klassen.

Weitere Informationen finden Sie im Oracle Tutorial . Durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Spezifikation ist JSR 31 .

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 Zeichenfolgen oder Java.sql. * -Klassen erforderlich.

Woher bekommen Sie die Java.time-Klassen?

Das Projekt ThreeTen-Extra erweitert Java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von Java.time. Hier finden Sie möglicherweise einige nützliche Klassen wie Interval , YearWeek , YearQuarter und mehr .

11
Basil Bourque

Bei Java 8 sollte das neue Java.time-Paket verwendet werden.

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

Sie können ein ZonedDateTime Objekt aus einem alten Java.util.Date Objekt wie folgt erstellen:

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

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

  1. die API ist konsistent und intuitiv. Im Gegensatz zu den Java.util.Date/Calendar-APIs
  2. im Gegensatz zu Java.text.SimpleDateFormat etc. gibt es keine Threading-Probleme. (Ich habe zahlreiche Client-Probleme festgestellt, die sich darauf beziehen, dass die Standardformatierung von Datum und Uhrzeit nicht threadsicher ist.)
  3. es ist die Basis der neuen Java-Datums-/Zeit-APIs ( JSR310 , geplant für Java 8. Daher werden Sie APIs verwenden, die zu zentralen Java-APIs werden.

BEARBEITEN: Die mit Java 8 eingeführten Java-Klassen für Datum und Uhrzeit sind jetzt die bevorzugte Lösung, wenn Sie zu Java 8 migrieren können

9
Brian Agnew

Ein bisschen spät auf Party, aber Java hat eine neue Datums-Zeit-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.

8
Silviu Burcea

Datum sollte neu entwickelt werden. Anstatt lange Zeit zu verlieren, sollte es Jahr, Monat, Datum, Stunde, Minute, Sekunde als separate Felder enthalten. Es kann sogar sinnvoll sein, den Kalender und die Zeitzone zu speichern, der dieses Datum zugeordnet ist.

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

Wenn Date als lange Ganzzahl (von Millisekunden seit dem 1. Januar 1970 oder so) gespeichert wird, hängt die Berechnung des aktuellen Datums vom Kalender ab. Unterschiedliche Kalender geben unterschiedliche Datumsangaben an. Dies ist von der Perspektive, eine absolute Zeit anzugeben (zB 1 Billion Sekunden nach dem Urknall). Oft brauchen wir aber auch eine bequeme Art des Gesprächs, beispielsweise ein Objekt, das Jahr, Monat usw. enthält.

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

1
user2835562

Ich verwende Kalender, wenn ich bestimmte Datumsangaben wie das Verschieben in der Zeit benötige, aber Datum finde ich hilfreich, wenn Sie das Datum formatieren müssen, um Ihre Anforderungen anzupassen. Kürzlich habe ich herausgefunden, dass Locale viele nützliche Operationen und Methoden hat. So Ich verwende jetzt Locale!

0
Brian Nelson

Übrigens ist "date" normalerweise mit "obsolete/deprecated" gekennzeichnet (ich weiß nicht genau warum) - irgendetwas darüber wird dort geschrieben Java: Warum ist der Date-Konstruktor veraltet, und was verwende ich stattdessen?

Es sieht so aus, als wäre es ein Problem des Konstruktors nur über neues Datum (int. Jahr, int. Monat, int. Tag), empfohlener Weg ist über Kalender und die Einstellung der Parameter getrennt .. (Kalender cal = Calendar.getInstance (); )

0
xxxvodnikxxx