JavaRush /Java-Blog /Random-DE /Eine intuitive, robuste Bibliothek zum Arbeiten mit Zeite...
theGrass
Level 24
Саратов

Eine intuitive, robuste Bibliothek zum Arbeiten mit Zeiten und Daten ist endlich in Java verfügbar (Teil 1).

Veröffentlicht in der Gruppe Random-DE
Java bietet     endlich eine intuitive und zuverlässige Möglichkeit, mit Datums- und Uhrzeitangaben zu arbeiten. Die Prinzipien von Datum und Uhrzeit sind in vielen Anwendungen von grundlegender Bedeutung. Verschiedene Dinge wie Geburtsdaten, Mietdaten, Veranstaltungszeiten und Ladenöffnungszeiten basieren alle auf Datum und Uhrzeit, aber Java SE bot keine bequeme Möglichkeit, damit zu arbeiten. Ab Java SE 8 gab es eine Reihe von java.time- Paketen , die eine gut strukturierte API für die Arbeit mit Datums- und Uhrzeitangaben bereitstellen.
Hintergrund
    Als Java in Version 1.0 zum ersten Mal herauskam , war java.util.Date die einzige Klasse für die Arbeit mit Datums- und Uhrzeitangaben . Das erste, was den Entwicklern auffiel, war, dass es sich nicht um ein „Datum“ handelte. Tatsächlich stellt es einen auf Millisekunden genauen Zeitpunkt dar, gemessen ab dem 1. Januar 1970. Aufgrund der Tatsache, dass die toString()- Methode von Date Datum und Uhrzeit in der in den Java- Einstellungen der Maschine angegebenen Zeitzone anzeigt , kamen einige Entwickler jedoch fälschlicherweise zu dem Schluss, dass Date mit Zeitzonen arbeiten kann. Das Reparieren dieser Klasse erwies sich als so schwierig (oder so faul), dass wir in Version 1.1 eine neue Klasse hinzufügen mussten – java.util.Calendar . Leider erwies sich die Klasse Calendar als nicht viel besser als Date . Hier ist eine kleine Liste bestehender Probleme bei der Umsetzung:
  • Veränderbar. Klassen wie Datum und Uhrzeit sollten unveränderlich sein.
  • Offsets. Die Jahre in der Datumsklasse beginnen bei 1900, die Monate in beiden Klassen beginnen bei Null.
  • Namen. „Datum“ ist eigentlich kein „Datum“, und „Kalender“ ist kein Kalender.
  • Formatierung. Die Formatierung funktioniert nur mit Datum, nicht mit Kalender, und ist nicht threadsicher.
    Im Jahr 2001 entstand das Joda-Time- Projekt . Sein Ziel war einfach: eine hochwertige Bibliothek für die Arbeit mit Datums- und Uhrzeitangaben in Java zu erstellen . Es dauerte einige Zeit, aber schließlich wurde Version 1.0 veröffentlicht und erfreute sich schnell großer Beliebtheit und großer Verbreitung. Im Laufe der Zeit forderten Entwickler zunehmend die Bereitstellung einer ähnlich praktischen Bibliothek als Teil des JDK . Unter Beteiligung von Michael Nascimento Santos aus Brasilien wurde das JSR-310- Projekt gestartet , das den offiziellen Prozess zur Erstellung und Integration einer neuen API für die Arbeit mit Datums- und Uhrzeitangaben im JDK darstellt .
Rezension
Die neue java.time API enthält 5 Pakete:
  • java.time – das Basispaket, das Objekte zum Speichern von Werten enthält
  • java.time.chrono – bietet Zugriff auf verschiedene Kalender
  • java.time.format – Formatierung und Erkennung von Datum und Uhrzeit
  • java.time.temporal – Low-Level-Bibliotheken und erweiterte Funktionalität
  • java.time.zone – Klassen für die Arbeit mit Zeitzonen
    Die meisten Entwickler verwenden hauptsächlich das Basispaket und die Formatierung und möglicherweise java.time.temporal . Obwohl also 68 neue Typen hinzugefügt wurden, werden Entwickler nur etwa ein Drittel davon verwenden.
Termine
Die LocalDate-     Klasse ist eine der wichtigsten in der neuen API . Es enthält einen unveränderlichen Wert, der ein Datum darstellt. Sie können weder die Uhrzeit noch die Zeitzone einstellen. Der Name „local“ ist Ihnen vielleicht von Joda-Time bekannt und stammt ursprünglich aus dem ISO-8601- Standard . Es bedeutet genau das Fehlen einer Zeitzone. Im Wesentlichen handelt es sich bei LocalDate um eine Beschreibung eines Datums, beispielsweise „5. April 2014“. Die tatsächliche Uhrzeit dieses Datums hängt von Ihrer Zeitzone ab. In Australien liegt dieses Datum beispielsweise 10 Stunden früher als in London und 18 Stunden früher als in San Francisco. Die LocalDate- Klasse verfügt über alle häufig benötigten Methoden: LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     In unserem Beispiel sehen wir ein Datum, das mit einer Factory-Methode erstellt wurde (alle Konstruktoren sind privat). Als nächstes fragen wir das Objekt nach einigen Daten. Bitte beachten Sie, dass die Aufzählungen „Month“ und „DayOfWeek“ dazu dienen, den Code lesbarer und zuverlässiger zu machen. Im folgenden Beispiel sehen wir, wie man das Datum ändert. Da die Klasse unveränderlich ist, werden als Ergebnis neue Objekte entstehen, das Original bleibt jedoch so, wie es war. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     Dabei handelt es sich um relativ einfache Änderungen, häufig müssen jedoch komplexere Datumsänderungen vorgenommen werden. Dafür gibt es einen speziellen Mechanismus in der java.time API – TemporalAdjuster . Sein Zweck besteht darin, ein integriertes Tool bereitzustellen, mit dem Sie Datumsangaben manipulieren können, beispielsweise um ein Objekt abzurufen, das dem letzten Tag des Monats entspricht. Einige davon sind in der API enthalten , Sie können jedoch Ihre eigenen hinzufügen. Die Verwendung von Modifikatoren ist sehr einfach, erfordert jedoch statische Importe: import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     Die Verwendung von Modifikatoren vereinfacht Ihren Code erheblich. Niemand möchte viel manuelle Datumsmanipulation sehen. Wenn in Ihrem Projekt mehrmals eine Datumsmanipulation auftritt, schreiben Sie Ihren eigenen Modifikator und Ihr Team kann ihn als bereits geschriebene und getestete Komponente verwenden.
Uhrzeit und Datum als Werte
    Es lohnt sich, ein wenig Zeit damit zu verbringen, zu verstehen, was LocalDate so wertvoll macht. Werte sind einfache Datentypen, die vollständig austauschbar sind; wenn sie gleich sind, verliert die Identität der Objekte ihre Bedeutung. Ein klassisches Beispiel für eine Wertklasse ist String . Wir vergleichen Zeichenfolgen mit equal() und es ist uns egal, ob die Objekte beim Vergleich mit dem ==- Operator identisch sind . Die meisten Klassen für die Arbeit mit Datums- und Uhrzeitangaben sind ebenfalls Werte. Daher ist es eine schlechte Idee, sie mit dem ==- Operator zu vergleichen, wie in der Dokumentation angegeben. Für diejenigen, die mehr erfahren möchten, schauen Sie sich meine aktuelle Definition von VALJOs an , die einen strengen Satz von Regeln umreißt, denen Wertobjekte in Java folgen müssen , einschließlich Unveränderlichkeit, Factory-Methoden und der richtigen Definition von equal() , hashCode , toString() , und vergleichenTo. () .
Alternative Kalender
Die LocalDate-     Klasse ist wie alle Hauptklassen in java.time an einen einzigen Kalender gebunden – wie im ISO-8601- Standard beschrieben . Standard 8601 beschreibt den weltweiten Standardkalender, auch Gregorianischer Kalender genannt. Ein Standardjahr umfasst 365 Tage, ein Schaltjahr 366. Jedes vierte Jahr ist ein Schaltjahr, es sei denn, es ist durch 100 oder durch 400 teilbar. Das Jahr vor dem ersten Jahr einer neuen Ära wird zur Vereinfachung der Berechnung als Null betrachtet. Die erste Konsequenz dieses Standardsystems besteht darin, dass die Ergebnisse nicht immer mit denen übereinstimmen, die mit GregorianCalendar berechnet wurden . Die GregorianCalendar- Klasse verfügt über einen integrierten Wechsel zum julianischen System für alle Daten vor dem 15. Oktober 1582. Im Julianischen System war ausnahmslos jedes vierte Jahr ein Schaltjahr. Die Frage ist: Da der Übergang von einem System zu einem anderen eine historische Tatsache ist, warum modelliert java.time ihn nicht? Ja, weil verschiedene Länder zu unterschiedlichen Zeiten auf das gregorianische System umgestiegen sind und wir nur das Datum des vatikanischen Übergangs berücksichtigen, werden wir für die meisten anderen Länder falsche Daten erhalten. Beispielsweise stellte das Britische Empire, einschließlich der Kolonien in Nordamerika, am 14. September 1752, fast 200 Jahre später, auf den Gregorianischen Kalender um. Russland änderte seinen Kalender erst am 14. Februar 1918, und Schwedens Übergang ist im Allgemeinen eine unklare Angelegenheit. Daher variiert die tatsächliche Bedeutung von Daten vor 1918 je nach den Umständen stark. Die Autoren des LocalDate- Codes haben eine völlig rationale Entscheidung getroffen, den Übergang vom Julianischen Kalender zum Gregorianischen Kalender überhaupt nicht zu modellieren, um Unstimmigkeiten zu vermeiden. Die zweite Konsequenz der Verwendung von ISO-8601 als Standardkalender in allen Kernklassen besteht darin, dass ein zusätzlicher Satz von Klassen erforderlich ist, um die verbleibenden Kalender zu verarbeiten. Die Chronologie- Schnittstelle ist die Grundlage für die Arbeit mit alternativen Kalendern und ermöglicht es Ihnen, den gewünschten Kalender anhand des Gebietsschemanamens zu finden. Java 8 enthält vier zusätzliche Kalender: Thai-Buddhismus, Mingguo (Taiwanesisch), Japanisch und Islamisch. Andere Kalender werden möglicherweise mit Programmen geliefert. Jeder Kalender verfügt über eine spezielle Datumsklasse wie ThaiBuddhistDate , MinguoDate , JapaneseDate und HijrahDate . Es ist sinnvoll, sie in sehr stark lokalisierten Anwendungen einzusetzen, beispielsweise für die japanische Regierung. Eine zusätzliche Schnittstelle, ChronoLocalDate , wird zusammen mit LocalDate als Kernabstraktion der vier oben genannten Klassen verwendet , wodurch Sie Code unabhängig vom verwendeten Kalendertyp schreiben können. Obwohl diese Abstraktion existiert, wird ihre Verwendung nicht empfohlen. Um zu verstehen, wie die gesamte java.time-API funktioniert, ist es wichtig zu verstehen, warum diese Abstraktion nicht empfohlen wird . Das Fazit ist, dass sich der Großteil des Codes, der ohne Bezug auf einen bestimmten Kalender geschrieben wird, als nicht funktionsfähig erweist. Sie können beispielsweise nicht sicher sein, dass ein Jahr 12 Monate hat, aber einige Entwickler addieren 12 Monate und denken, dass sie ein ganzes Jahr hinzugefügt haben. Sie können nicht sicher sein, dass alle Monate ungefähr die gleiche Anzahl von Tagen haben – im koptischen Kalender gibt es 12 Monate mit 30 Tagen und 1 Monat mit fünf oder sechs Tagen. Außerdem können Sie nicht sicher sein, dass die Zahl des nächsten Jahres um 1 höher sein wird als die des aktuellen, da im japanischen Kalender die Jahre ab der Proklamation des nächsten Kaisers gezählt werden (in diesem Fall sogar zwei Tage desselben Monats). kann verschiedenen Jahren angehören). Die einzige Möglichkeit, qualitativ hochwertigen und funktionierenden Code zu schreiben, der mit mehreren Kalendern gleichzeitig funktioniert, besteht darin, dass der Kern Ihres Codes, der alle Operationen an Datums- und Uhrzeitangaben ausführt, unter Verwendung eines Standardkalenders und nur bei der Eingabe/Ausgabe von Datumsangaben geschrieben werden muss soll es auf andere Kalendersysteme umgestellt werden. Das heißt, es wird empfohlen, LocalDate für die Speicherung und alle Datumsmanipulationen in Ihrer Anwendung zu verwenden . Und nur beim Lokalisieren von Eingabe- und Ausgabedaten sollten Sie ChronoLocalDate verwenden , das normalerweise aus der im Benutzerprofil gespeicherten Kalenderklasse abgerufen wird. Es stimmt, dass die meisten Anwendungen keine so ernsthafte Lokalisierung benötigen. Wenn Sie eine ausführlichere Erklärung zu allem, was in diesem Kapitel beschrieben wird, benötigen, willkommen in der Dokumentation der ChronoLocalDate- Klasse .      Fortsetzung des Artikels      Originalartikel
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION