Was ist falsch an der Java Date & Time API? [geschlossen]

105

Sehr oft stoße ich auf negatives Feedback zu Java Dateund anderen datums- und zeitbezogenen Klassen. Als .NET-Entwickler kann ich nicht vollständig (ohne sie verwendet zu haben) verstehen, was mit ihnen tatsächlich falsch ist.

Kann jemand etwas Licht ins Dunkel bringen?

Anton Gogolev
quelle

Antworten:

142

Ah, die Java- DateKlasse. Vielleicht eines der besten Beispiele dafür, wie man irgendwo in keiner Sprache etwas macht. Wo soll ich anfangen?

Das Lesen des JavaDoc könnte zu der Annahme führen, dass die Entwickler tatsächlich einige gute Ideen haben. Es geht ausführlich um den Unterschied zwischen UTC und GMT , obwohl der Unterschied zwischen den beiden im Grunde genommen Schaltsekunden beträgt (was ziemlich selten vorkommt ).

Bei den Entwurfsentscheidungen ging es jedoch wirklich darum, den Gedanken zu verschwenden, eine gut gestaltete API zu sein. Hier sind einige der beliebtesten Fehler:

  • Obwohl es im letzten Jahrzehnt des Jahrtausends entworfen wurde, werden Jahre seit 1900 zweistellig bewertet. Aufgrund dieser banalen Entscheidung gibt es in der Java-Welt buchstäblich Millionen von Problemumgehungen, die 1900+ (oder 1900-) lösen.
  • Die Monate sind auf Null indiziert, um dem spektakulär ungewöhnlichen Fall gerecht zu werden, dass ein Array von Monaten vorhanden ist und nicht mit einem Array mit dreizehn Elementen lebt, von denen das erste a enthält null. Als Ergebnis haben wir 0..11 (und heute ist Monat 11 des Jahres 109). Es gibt eine ähnliche Anzahl von ++ und - in den Monaten, um in einen String zu konvertieren.
  • Sie sind veränderlich . Daher müssen Sie jedes Mal, wenn Sie ein Datum zurückgeben möchten (z. B. als Instanzstruktur), einen Klon dieses Datums anstelle des Datumsobjekts selbst zurückgeben (da sonst Personen Ihre Struktur mutieren können).
  • Das Calendar, das entwickelt wurde, um dies zu beheben, macht tatsächlich die gleichen Fehler. Sie sind immer noch veränderlich.
  • Datestellt a dar DateTime, aber um sich auf diejenigen im SQL-Land zu beschränken, gibt es eine andere Unterklasse java.sql.Date, die einen einzelnen Tag darstellt (allerdings ohne eine damit verbundene Zeitzone).
  • Es gibt keine TimeZones, die mit a verknüpft sind Date, und daher werden Bereiche (z. B. ein "ganzer Tag") häufig als Mitternacht-Mitternacht dargestellt (häufig in einer beliebigen Zeitzone).

Schließlich ist anzumerken, dass sich Schaltsekunden im Allgemeinen gegen eine gute Systemuhr korrigieren, die innerhalb einer Stunde mit ntp aktualisiert wird (siehe Links unten). Die Wahrscheinlichkeit, dass ein System nach zwei Schaltsekunden (mindestens alle sechs Monate, praktisch alle paar Jahre) noch betriebsbereit ist, ist ziemlich unwahrscheinlich, insbesondere angesichts der Tatsache, dass Sie von Zeit zu Zeit neue Versionen Ihres Codes erneut bereitstellen müssen . Selbst die Verwendung einer dynamischen Sprache, die Klassen oder etwas wie eine WAR-Engine neu generiert, verschmutzt den Klassenraum und hat schließlich kein Permgen mehr.

AlBlue
quelle
43

JSR 310 , das in Java 8 die alten Datums- / Uhrzeitklassen durch java.time ersetzte , begründet sich im ursprünglichen JSR wie folgt:

2.5 Welchen Bedarf der Java-Community wird in der vorgeschlagenen Spezifikation berücksichtigt?

Derzeit verfügt Java SE über zwei separate Datums- und Uhrzeit-APIs - java.util.Date und java.util.Calendar. Beide APIs werden von Java-Entwicklern in Weblogs und Foren durchweg als schwierig zu verwenden beschrieben. Insbesondere verwenden beide monatelang einen Nullindex, was eine Ursache für viele Fehler ist. Der Kalender hat im Laufe der Jahre auch unter vielen Fehlern und Leistungsproblemen gelitten, hauptsächlich aufgrund der internen Speicherung seines Status auf zwei verschiedene Arten.

Ein klassischer Fehler (4639407) verhinderte, dass bestimmte Daten in einem Kalenderobjekt erstellt wurden. Es könnte eine Codesequenz geschrieben werden, die in einigen Jahren ein Datum erstellen könnte, in anderen jedoch nicht, wodurch verhindert wird, dass einige Benutzer ihre korrekten Geburtsdaten eingeben. Dies wurde durch die Kalenderklasse verursacht, die im Sommer nur einen Sommerzeitgewinn von einer Stunde zuließ, während es in der Vergangenheit um die Zeit des Zweiten Weltkriegs plus 2 Stunden waren. Während dieser Fehler jetzt behoben ist, würde die Kalenderklasse erneut unterbrochen, wenn ein Land irgendwann in der Zukunft einen Sommerzeitgewinn von plus drei Stunden einführen würde.

Die aktuelle Java SE-API leidet auch in Multithread-Umgebungen. Unveränderliche Klassen sind bekanntermaßen von Natur aus threadsicher, da sich ihr Status nicht ändern kann. Sowohl Datum als auch Kalender sind jedoch veränderbar, sodass Programmierer das Klonen und Threading explizit berücksichtigen müssen. Darüber hinaus ist der Mangel an Thread-Sicherheit in DateTimeFormat nicht allgemein bekannt und hat viele schwer zu ermittelnde Threading-Probleme verursacht.

Neben den Problemen mit den Klassen, die Java SE für datetime hat, gibt es keine Klassen zum Modellieren anderer Konzepte. Nicht-Zeitzonendaten oder -zeiten, -dauern, -perioden und -intervalle haben in Java SE keine Klassendarstellung. Infolgedessen verwenden Entwickler häufig ein int, um eine Zeitdauer darzustellen, wobei javadoc die Einheit angibt.

Das Fehlen eines umfassenden Datums- und Zeitmodells führt auch dazu, dass viele gängige Operationen schwieriger sind, als sie sein sollten. Beispielsweise ist die Berechnung der Anzahl der Tage zwischen zwei Daten derzeit ein besonders schwieriges Problem.

Dieses JSR wird das Problem eines vollständigen Datums- und Zeitmodells angehen, einschließlich Datum und Uhrzeit (mit und ohne Zeitzonen), Dauer und Zeiträumen, Intervallen, Formatierung und Analyse.

Meriton
quelle
28
  • Datumsinstanzen sind veränderbar , was fast immer unpraktisch ist.
  • Sie haben eine doppelte Natur. Sie repräsentieren sowohl einen Zeitstempel als auch ein Kalenderdatum. Es stellt sich heraus, dass dies bei der Berechnung von Daten problematisch ist.
  • Die numerischen Darstellungen von Kalenderdaten sind in vielen Fällen nicht intuitiv. Zum Beispiel: getMonth()ist nullbasiert, getYear()ist 1900basiert (dh das Jahr 2009 wird als 109 dargestellt).
  • Ihnen fehlen viele Funktionen, die Sie von einer DateKlasse erwarten .
Seidenschwanz
quelle
13

Ich fühle für Sie ... als ehemaliger .NET-Programmierer habe ich die gleichen Fragen gestellt, die Zeit-API in .NET (Zeitspannen, Überladen von Operatoren) ist sehr praktisch.

Um ein bestimmtes Datum zu erstellen, verwenden Sie zunächst entweder eine veraltete API oder:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

Um einen Tag abzuziehen, machst du böse Dinge wie

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

oder schlimmer

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

Um herauszufinden, wie viel Zeit zwischen zwei Daten vergangen ist (in Tagen / Wochen / Monaten) ... wird es noch schlimmer

Jedoch DateUtils von Apache ( org.apache.commons.lang.time.DateUtils) einige praktische Methoden bieten und ich fand mich mit ihnen nur in letzter Zeit

Wie Brabster schrieb, ist Joda Time auch eine gute externe Bibliothek, aber Apache scheint "häufiger" zu sein als alles andere ...

Eran Medan
quelle
Bitte-bitte, zeigen Sie uns, wie das geht ("Finden Sie heraus, wie viel Zeit zwischen zwei Daten vergangen ist")!
Anton Gogolev
Ich wünschte, ich wüsste einen einfachen Weg ... einschließlich Schaltjahren, nervösen Monaten und flüchtigen Tagen ...
Eran Medan
1
Siehe auch org.apache.commons.lang.time: commons.apache.org/lang//api/org/apache/commons/lang/time/…
trashgod
@AntonGogolev In java.time , Verwendung Periodund DurationKlassen zu berechnen und die verstrichene Zeit auf einer Skala von Jahren-Monate-Tagen und Stunden-Minuten-Sekunden jeweils darstellen.
Basil Bourque
4

Ich finde Javas Date API verwendbar, um ehrlich zu sein. Die meisten der Fragen , die ich je gesehen habe und gehört beziehen sich etwa auf die Ausführlichkeit, die Notwendigkeit, mehrere Klassen beinhalten , etwas zu tun nützlich ( Calendar, Date, DateFormat/ SimpleDateFormat) und das Fehlen von einfachen Zugriffsmethoden wie getDayOfWeek().

Joda Time ist eine angesehene alternative API in Java. Im Abschnitt Warum Joda Time finden Sie weitere Argumente, warum es sich um eine praktikable Alternative handelt, die von Interesse sein könnte.

Brabster
quelle