From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100109.html | 787 +++++++++++++++++++++ 1 file changed, 787 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100109.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100109.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100109.html b/Master/Reference Architectures and Patterns/hjp5/html/k100109.html new file mode 100644 index 0000000..16fd1bd --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100109.html @@ -0,0 +1,787 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 16 - Utility-Klassen I +
+
+ + + + +

16.2 Die Klassen Date, Calendar und GregorianCalendar +

+
+ +
+ +

+Bis zum JDK 1.0.2 war die Klasse Date +zur Darstellung und Manipulation von Datumswerten vorgesehen. Leider +war sie nicht ganz fehlerfrei und aufgrund diverser Einschränkungen +nur sehr bedingt zu gebrauchen. Ab der Version 1.1 des JDK gibt es +neben Date +die Klasse Calendar +zur Verarbeitung von Datumswerten. Obgleich der Name den Anschein +erwecken mag, dass ein Objekt vom Typ Calendar +ein visueller Kalender ist, der als Komponente in GUI-basierten Programmen +verwendet werden kann, ist dies nicht richtig. Statt dessen stellt +Calendar +eine Kapselung für Date +dar, deren Aufgabe es ist, ein Datum-/Uhrzeitobjekt zu realisieren +und Methoden zur Konstruktion, zum Verändern und Auslesen von +Datums-/Uhrzeitbestandteilen und für die Zeit- und Datumsarithmetik +zur Verfügung zu stellen. + +

+Zunächst ist Calendar +nichts weiter als eine abstrakte Basisklasse. Sie enthält die +Methoden, mit denen auf die einzelnen Elemente konkreter Kalenderklassen +zugegriffen werden kann bzw. mit denen diese Klassen manipuliert werden +können. Als einzige konkrete Ableitung von Calendar +steht die Klasse GregorianCalendar +zur Verfügung, die ein Datum nach dem hierzulande verwendeten +gregorianischen Kalender implementiert. Die Komplexität der Klassen +Calendar +und GregorianCalendar +kommt vor allem durch folgende Ursachen zustande: +

+ +

+In der Tat ist die Implementierung der Kalenderklassen des JDK komplex +und war lange Zeit fehlerbehaftet. Sie wird insbesondere dadurch erschwert, +dass ein Datumsobjekt nicht nur aus den einzelnen Feldern für +Tag, Monat, Jahr usw. besteht, sondern zusätzlich einen ganzzahligen +Wert des Typs long +enthält, der das Datum als Anzahl der Millisekunden seit dem +1.1.1970 speichert. Beide Werte müssen auch nach Veränderungen +einzelner Bestandteile des Datumsobjekts konsistent gehalten werden. + +

+Auch die Bedienung der Kalenderklassen ist nicht so eingängig +wie in vielen anderen Programmiersprachen. Hinderlich ist dabei oft +die Tatsache, dass neben Datum und Uhrzeit grundsätzlich auch +die Zeitzone mit betrachtet wird. Wir wollen in diesem Abschnitt einen +pragmatischen Ansatz wählen und nur die wesentlichen Eigenschaften +der beiden Klassen vorstellen. Fortgeschrittenere Themen wie Zeitzonenkalkulation +oder Lokalisierung werden außen vor bleiben. + + + + +

16.2.1 Konstruktoren

+ +

+Da die Klasse Calendar +abstrakt ist, müssen konkrete Datumsobjekte aus der Klasse GregorianCalendar +erzeugt werden. Dazu stehen folgende Konstruktoren zur Verfügung: +

+ + + + + +
+ +
+public GregorianCalendar()
+
+public GregorianCalendar(int year, int month, int date)
+
+public GregorianCalendar(
+   int year, int month, int date,
+   int hour, int minute
+)
+
+public GregorianCalendar(
+   int year, int month, int date,
+   int hour, int minute, int second
+)
+
+
+
+java.util.GregorianCalendar
+ +

+Der parameterlose Konstruktor initialisiert das Datumsobjekt mit dem +aktuellen Datum und der aktuellen Uhrzeit. Die übrigen Konstruktoren +weisen die als Parameter übergebenen Werte zu. Neben den hier +vorgestellten Konstruktoren gibt es noch weitere, die es erlauben, +die Zeitzone und Lokalisierung zu verändern. Standardmäßig +werden die lokale Zeitzone und die aktuelle Lokalisierung verwendet. + + + + +

16.2.2 Abfragen und Setzen von Datumsbestandteilen

+ +

+Das Abfragen und Setzen von Datumsbestandteilen erfolgt mit den Methoden +set +und get: +

+ + + + + +
+ +
+public final int get(int field)
+
+public final void set(int field, int value)
+
+
+
+java.util.Calendar
+ +

+get +und set +erwarten als erstes Argument einen Feldbezeichner, der angibt, auf +welches der diversen Datums-/Zeitfelder des Objektes zugegriffen werden +soll. Als Rückgabewert liefert get +den Inhalt des angegebenen Feldes; set +schreibt den als zweiten Parameter value +übergebenen Wert in das Feld hinein. Tabelle 16.1 +gibt eine Übersicht der in Calendar +vorgesehenen Feldbezeichner, ihrer Wertegrenzen und Bedeutung: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeldbezeichnerMinimalwertMaximalwertBedeutung
Calendar.ERA01Ära
Calendar.YEAR15,000,000Jahr
Calendar.MONTH011Monat - 1
Calendar.WEEK_OF_YEAR154Woche im Jahr
Calendar.WEEK_OF_MONTH16Woche im Monat
Calendar.DAY_OF_MONTH131Tag im Monat
Calendar.DAY_OF_YEAR1366Tag im Jahr
Calendar.DAY_OF_WEEK17Wochentag
Calendar.DAY_OF_WEEK_IN_MONTH-16Wochentagswiederholung im Monat
Calendar.AM_PM01Vor-/nachmittags
Calendar.HOUR012Amerik. Stunde
Calendar.HOUR_OF_DAY023Stunde
Calendar.MINUTE059Minute
Calendar.SECOND059Sekunde
Calendar.MILLISECOND0999Millisekunde
Calendar.ZONE_OFFSET-12*60*60*100012*60*60*1000Zeitzonenoffset
Calendar.DST_OFFSET01*60*60*1000Sommerzeitoffset
+

+Tabelle 16.1: Feldbezeichner der Klasse Calendar

+

+ + + + + + + + + +
+ +

+Hierbei gibt es einige Besonderheiten zu beachten. So wird beispielsweise +der Monat nicht von 1 bis 12 gemessen, sondern von 0 bis 11. Das Feld +ERA +gibt an, ob das Datum vor Christi Geburt oder danach liegt. DAY_OF_WEEK +geht von 1 = Sonntag bis 7 = Samstag, es stehen aber auch symbolische +Konstanten zur Verfügung. ZONE_OFFSET +und DST_OFFSET +sind die Zeitzonen- und Sommerzeitabweichungen, die in Millisekunden +gemessen werden.

+ + + + +
 Hinweis 
+
+ +

+Wir wollen uns die Verwendung der verschiedenen Felder an einem einfachen +Beispiel ansehen. Das Programm zeigt auch die Verwendung einiger symbolischer +Konstanten zur Darstellung von Wochentagen und der Ära (vor/nach +Christi Geburt): + + +

+ + + + + +
+ +
+001 /* Listing1602.java */
+002 
+003 import java.util.*;
+004 
+005 public class Listing1602
+006 {
+007   public static void main(String[] args)
+008   {
+009     //Zuerst Ausgabe des aktuellen Datums
+010     GregorianCalendar cal = new GregorianCalendar();
+011     //cal.setTimeZone(TimeZone.getTimeZone("ECT")); 
+012     printCalendarInfo(cal);
+013     System.out.println("---");
+014 
+015     //Nun Ausgabe der Informationen zum 22.6.1910,
+016     //dem Geburtstag von Konrad Zuse
+017     cal.set(Calendar.DATE, 22);
+018     cal.set(Calendar.MONTH, 6 - 1);
+019     cal.set(Calendar.YEAR, 1910);
+020     printCalendarInfo(cal);
+021     //cal.setTime(cal.getTime()); 
+022   }
+023 
+024   public static void printCalendarInfo(GregorianCalendar cal)
+025   {
+026     //Aera
+027     int value = cal.get(Calendar.ERA);
+028     if (value == cal.BC) {
+029       System.out.println("Aera.......: vor Christi Geburt");
+030     } else if (value == cal.AD) {
+031       System.out.println("Aera.......: Anno Domini");
+032     } else {
+033       System.out.println("Aera.......: unbekannt");
+034     }
+035     //Datum
+036     System.out.println(
+037       "Datum......: " +
+038       cal.get(Calendar.DATE) + "." +
+039       (cal.get(Calendar.MONTH)+1) + "." +
+040       cal.get(Calendar.YEAR)
+041     );
+042     //Zeit
+043     System.out.println(
+044       "Zeit.......: " +
+045       cal.get(Calendar.HOUR_OF_DAY) + ":" +
+046       cal.get(Calendar.MINUTE) + ":" +
+047       cal.get(Calendar.SECOND) + " (+" +
+048       cal.get(Calendar.MILLISECOND) + " ms)"
+049     );
+050     //Zeit, amerikanisch
+051     System.out.print(
+052       "Am.Zeit....: " +
+053       cal.get(Calendar.HOUR) + ":" +
+054       cal.get(Calendar.MINUTE) + ":" +
+055       cal.get(Calendar.SECOND)
+056     );
+057     value = cal.get(Calendar.AM_PM);
+058     if (value == cal.AM) {
+059       System.out.println(" AM");
+060     } else if (value == cal.PM) {
+061       System.out.println(" PM");
+062     }
+063     //Tag
+064     System.out.println(
+065       "Tag........: " +
+066       cal.get(Calendar.DAY_OF_YEAR) + ". im Jahr"
+067     );
+068     System.out.println(
+069       "             " +
+070       cal.get(Calendar.DAY_OF_MONTH) + ". im Monat"
+071     );
+072     //Woche
+073     System.out.println(
+074       "Woche......: " +
+075       cal.get(Calendar.WEEK_OF_YEAR) + ". im Jahr"
+076     );
+077     System.out.println(
+078       "             " +
+079       cal.get(Calendar.WEEK_OF_MONTH) + ". im Monat"
+080     );
+081     //Wochentag
+082     System.out.print(
+083       "Wochentag..: " +
+084       cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) +
+085       ". "
+086     );
+087     value = cal.get(Calendar.DAY_OF_WEEK);
+088     if (value == cal.SUNDAY) {
+089       System.out.print("Sonntag");
+090     } else if (value == cal.MONDAY) {
+091       System.out.print("Montag");
+092     } else if (value == cal.TUESDAY) {
+093       System.out.print("Dienstag");
+094     } else if (value == cal.WEDNESDAY) {
+095       System.out.print("Mittwoch");
+096     } else if (value == cal.THURSDAY) {
+097       System.out.print("Donnerstag");
+098     } else if (value == cal.FRIDAY) {
+099       System.out.print("Freitag");
+100     } else if (value == cal.SATURDAY) {
+101       System.out.print("Samstag");
+102     } else {
+103       System.out.print("unbekannt");
+104     }
+105     System.out.println(" im Monat");
+106     //Zeitzone
+107     System.out.println(
+108       "Zeitzone...: " +
+109       cal.get(Calendar.ZONE_OFFSET)/3600000 +
+110       " Stunden"
+111     );
+112     System.out.println(
+113       "Sommerzeit.: " +
+114       cal.get(Calendar.DST_OFFSET)/3600000 +
+115       " Stunden"
+116     );
+117   }
+118 }
+
+
+Listing1602.java
+ +Listing 16.2: Die Felder der Klasse Calendar

+ +

+Das Programm erzeugt zunächst ein GregorianCalendar-Objekt +für das aktuelle Tagesdatum und gibt die internen Feldwerte aus. +Anschließend ändert es durch mehrfachen Aufruf von set +das Datum in den 22.6.1910 ab und gibt die Felder erneut aus. Die +Ausgabe des Programms lautet: + +

+Aera.......: Anno Domini
+Datum......: 28.4.2000
+Zeit.......: 17:55:0 (+590 ms)
+Am.Zeit....: 5:55:0 PM
+Tag........: 119. im Jahr
+             28. im Monat
+Woche......: 17. im Jahr
+             4. im Monat
+Wochentag..: 4. Freitag im Monat
+Zeitzone...: 1 Stunden
+Sommerzeit.: 1 Stunden
+---
+Aera.......: Anno Domini
+Datum......: 22.6.1910
+Zeit.......: 17:55:0 (+590 ms)
+Am.Zeit....: 5:55:0 PM
+Tag........: 173. im Jahr
+             22. im Monat
+Woche......: 25. im Jahr
+             4. im Monat
+Wochentag..: 4. Mittwoch im Monat
+Zeitzone...: 1 Stunden
+Sommerzeit.: 1 Stunden
+
+ +

+ + + + + + + + + + + +
+ +

+Wie man sieht, werden sowohl Datums- als auch Zeitwerte korrekt ausgegeben. +Damit dieses und vergleichbare Programme auch in den JDK-1.1-Versionen +korrekt laufen, sind einige Besonderheiten zu beachten: +

    +
  • Wird das Datumsobjekt ohne explizite Zeitzonenangabe +konstruiert, so verwendet der Konstruktor die von der Methode TimeZone.getDefault +gelieferte Zeitzone, die ihrerseits aus dem System-Property user.timezone +generiert wird. Unter dem JDK 1.1 wurde dieses Property aber nicht +immer gefüllt und es war erforderlich, die Zeitzone per Hand +zu setzen. Im JDK 1.2 und späteren Versionen können wir +dagegen auf den Aufruf von setTimeZone +in Zeile 011 verzichten. +
  • Das zweite Problem rührt aus der oben erwähnten Schwierigkeit, +den internen Zeitwert und die Feldwerte korrekt zu synchronisieren. +Nach der Zuweisung eines neuen Datums im Beispielprogramm werden zwar +die Felder für Tag, Monat und Jahr korrekt gesetzt, die übrigen +aber leider nicht. Nach dieser Zuweisung wäre also die Ausgabe +des Wochentags fehlerhaft gewesen. Als Workaround könnte das +Beispielprogramm nach dem Aufruf der set-Methoden +einen Aufruf von setTime(getTime()) +verwenden, der interne Uhrzeit und Feldwerte abgleicht. Wir haben +das im Listing in der Zeile 021 +hinter dem Kommentar angedeutet. Auch das scheint seit dem JDK 1.2 +nicht mehr nötig zu sein. +
+
+ + + + +
 JDK1.1-6.0 
+
+ + + + +

16.2.3 Vergleiche und Datums-/Zeitarithmetik +

+ +

+Die Methoden equals, +before +und after +erlauben es, zwei Datumswerte auf ihre relative zeitliche Lage zueinander +zu vergleichen: +

+ + + + + +
+ +
+public boolean equals(Object obj)
+
+public boolean before(Object obj)
+
+public boolean after(Object obj)
+
+
+
+java.util.Calendar
+ +

+Mit Hilfe der Methode add +kann zu einem beliebigen Feld eines Calendar- +oder GregorianCalendar-Objekts +ein beliebiger positiver oder negativer Wert hinzugezählt werden: +

+ + + + + +
+ +
+public abstract void add(int field, int amount)
+
+
+
+java.util.Calendar
+ +

+Dabei ist es auch erlaubt, dass die Summe den für dieses Feld +erlaubten Grenzwert über- bzw. unterschreitet. In diesem Fall +wird der nächsthöherwertige Datums- bzw. Zeitbestandteil +entsprechend angepasst. + +

+Das folgende Programm konstruiert zunächst ein Datum für +den 30.10.1908 und gibt es aus. Anschließend wird zunächst +der Tag, dann der Monat und schließlich das Jahr je zweimal +um 1 erhöht. Nach erfolgter Ausgabe wird die Änderung schrittweise +wieder rückgängig gemacht und der ursprüngliche Wert +wieder erzeugt: + + +

+ + + + + +
+ +
+001 /* Listing1603.java */
+002 
+003 import java.util.*;
+004 
+005 public class Listing1603
+006 {
+007   public static void main(String[] args)
+008   {
+009     GregorianCalendar cal   = new GregorianCalendar();
+010     cal.set(Calendar.DATE, 30);
+011     cal.set(Calendar.MONTH, 10 - 1);
+012     cal.set(Calendar.YEAR, 1908);
+013     showDate(cal);
+014     addOne(cal, Calendar.DATE);
+015     addOne(cal, Calendar.DATE);
+016     addOne(cal, Calendar.MONTH);
+017     addOne(cal, Calendar.MONTH);
+018     addOne(cal, Calendar.YEAR);
+019     addOne(cal, Calendar.YEAR);
+020 
+021     cal.add(Calendar.DATE, -2);
+022     cal.add(Calendar.MONTH, -2);
+023     cal.add(Calendar.YEAR, -2);
+024     showDate(cal);
+025   }
+026 
+027   public static void addOne(Calendar cal, int field)
+028   {
+029     cal.add(field,1);
+030     showDate(cal);
+031   }
+032 
+033   public static void showDate(Calendar cal)
+034   {
+035     String ret = "";
+036     int    value = cal.get(Calendar.DAY_OF_WEEK);
+037 
+038     switch (value) {
+039     case Calendar.SUNDAY:
+040       ret += "Sonntag";
+041       break;
+042     case Calendar.MONDAY:
+043       ret += "Montag";
+044       break;
+045     case Calendar.TUESDAY:
+046       ret += "Dienstag";
+047       break;
+048     case Calendar.WEDNESDAY:
+049       ret += "Mittwoch";
+050       break;
+051     case Calendar.THURSDAY:
+052       ret += "Donnerstag";
+053       break;
+054     case Calendar.FRIDAY:
+055       ret += "Freitag";
+056       break;
+057     case Calendar.SATURDAY:
+058       ret += "Samstag";
+059       break;
+060     }
+061     ret += ", den ";
+062     ret += cal.get(Calendar.DATE) + ".";
+063     ret += (cal.get(Calendar.MONTH)+1) + ".";
+064     ret += cal.get(Calendar.YEAR);
+065     System.out.println(ret);
+066   }
+067 }
+
+
+Listing1603.java
+ +Listing 16.3: Datumsarithmetik

+ +

+Die Ausgabe des Programms lautet: + +

+Freitag, den 30.10.1908
+Samstag, den 31.10.1908
+Sonntag, den 1.11.1908
+Dienstag, den 1.12.1908
+Freitag, den 1.1.1909
+Samstag, den 1.1.1910
+Sonntag, den 1.1.1911
+Freitag, den 30.10.1908
+
+ + + + + +

16.2.4 Umwandlung zwischen Date und Calendar

+ +

+In der Praxis ist es mitunter erforderlich, zwischen den beiden konkurrierenden +Zeitdarstellungen der Klassen Date +und Calendar +hin- und herzuschalten. So ist beispielsweise der in JDBC (siehe Kapitel 42) +häufig verwendete SQL-Datentyp java.sql.Date +aus java.util.Date +abgeleitet und repräsentiert ein Datum als Anzahl der Millisekunden +seit dem 1.1.1970. Mit Hilfe der Methoden setTime +und getTime +können beide Darstellungen ineinander überführt werden: +

+ + + + + +
+ +
+public final Date getTime()
+
+public final void setTime(Date date)
+
+
+
+java.util.Calendar
+ +

+Ein Aufruf von getTime +liefert das Datum als Objekt des Typs Date. +Soll das Datum aus einem vorhandenen Date-Objekt +in ein Calendar-Objekt +übertragen werden, kann dazu die Methode setTime +aufgerufen werden. Die Klasse Date +kann weiterhin dazu verwendet werden, auf die Anzahl der Millisekunden +seit dem 1.1.1970 zuzugreifen: +

+ + + + + +
+ +
+public Date(long date)
+
+public long getTime()
+
+
+
+java.util.Date
+ +

+Der Konstruktor erzeugt aus dem long +ein Date-Objekt, +und die Methode getTime +kann dazu verwendet werden, zu einem gegebenen Date-Objekt +die Anzahl der Millisekunden seit dem 1.1.1970 zu ermitteln. +


+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3