From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+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.
+
+
+
+
+
+Da die Klasse Calendar
+abstrakt ist, müssen konkrete Datumsobjekte aus der Klasse GregorianCalendar
+erzeugt werden. Dazu stehen folgende Konstruktoren zur Verfügung:
+
+
+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.
+
+
+
+
+
+Das Abfragen und Setzen von Datumsbestandteilen erfolgt mit den Methoden
+set
+und get:
+
+
+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:
+
+
+
+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.
+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):
+
+
+
+
+
+
+ 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
+
+
+
+
+
+
+
+
+16.2.1 Konstruktoren
+
+
+
+
+
+
+
+
+
+
+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
+16.2.2 Abfragen und Setzen von Datumsbestandteilen
+
+
+
+
+
+
+
+
+
+
+public final int get(int field)
+
+public final void set(int field, int value)
+
+
+
+java.util.Calendar
+
+
+
+
+
+Feldbezeichner
+Minimalwert
+Maximalwert
+Bedeutung
+
+Calendar.ERA
+0
+1
+Ära
+
+Calendar.YEAR
+1
+5,000,000
+Jahr
+
+Calendar.MONTH
+0
+11
+Monat - 1
+
+Calendar.WEEK_OF_YEAR
+1
+54
+Woche im Jahr
+
+Calendar.WEEK_OF_MONTH
+1
+6
+Woche im Monat
+
+Calendar.DAY_OF_MONTH
+1
+31
+Tag im Monat
+
+Calendar.DAY_OF_YEAR
+1
+366
+Tag im Jahr
+
+Calendar.DAY_OF_WEEK
+1
+7
+Wochentag
+
+Calendar.DAY_OF_WEEK_IN_MONTH
+-1
+6
+Wochentagswiederholung im Monat
+
+Calendar.AM_PM
+0
+1
+Vor-/nachmittags
+
+Calendar.HOUR
+0
+12
+Amerik. Stunde
+
+Calendar.HOUR_OF_DAY
+0
+23
+Stunde
+
+Calendar.MINUTE
+0
+59
+Minute
+
+Calendar.SECOND
+0
+59
+Sekunde
+
+Calendar.MILLISECOND
+0
+999
+Millisekunde
+
+Calendar.ZONE_OFFSET
+-12*60*60*1000
+12*60*60*1000
+Zeitzonenoffset
+
+Calendar.DST_OFFSET
+0
+1*60*60*1000
+Sommerzeitoffset
+
+
+
+
+
+
+![]()
+
+
+
+![]()
+
+
+
+
+
+ Hinweis
+
+
+
+
+Listing 16.2: Die Felder der Klasse Calendar
+
+
+
+
+
+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
+
+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: +
|
+
+
|
+![]() |
+
+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 | +
+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
+
+
+
+
+
+
+
+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 + |