Bei der Durchsicht der Java Datum Klassen beschleicht mich immer das Gefühl, die Entwickler dieser Klassen hatten den Ehrgeiz, eine Software zu entwickeln, die auch dann noch korrekte Angaben liefert, wenn sie auf dem Raumschiff Enterprise Bordcomputer im Moment einer katapultartigen Wurmloch-Passage ausgeführt wird.
Aber: alles halb so schlimm, denn zu 95 Prozent hat man es mit Formatierungsroutinen zu tun, entweder
um ein Datum als String abzuspeichern, oder von einem abgespeicherten String einzulesen. Und hierfür
gibt es eine einfache Klasse, die treffender Weise
SimpleDateFormat
heißt.
Bei Verwendung dieser Klasse ist für jede spezifische Formatierung eine eigene Instanz unter Vorgabe
des entsprechenden Musters zu erzeugen:
import java.util.*; import java.text.*; public class DateExample1 { private static SimpleDateFormat sdFormatter1 = new SimpleDateFormat("yyyy-MM-dd"); private static SimpleDateFormat sdFormatter2 = new SimpleDateFormat("dd.MM.yyyy"); public static void main(String[] args) throws ParseException { Date toDay = new Date(); System.out.println(sdFormatter1.format(toDay)); Date date = sdFormatter2.parse("29.02.2000"); System.out.println(sdFormatter1.format(date)); } }
C:\temp>java DateExample1 2009-02-03 2000-02-29
Ebenso gut lässt sich die Klasse SimpleDateFormat
verwenden, um Datum-Strings, die
nicht in einer unmittelbar sortierbaren Form vorliegen, zu vergleichen. Dazu werden die Strings
in Objekte des Typs Date konvertiert, die dann verglichen werden können:
Date date1 = sdFormatter.parse(dateString1);
Date date2 = sdFormatter.parse(dateString2);
return date1.compareTo(date2);
wobei als Ergebnis dieses Vergleichs
-1
wenn date1 < date2
0
wenn date1 = date2
1
wenn date1 > date2
geliefert wird.
Und um dieses Beispiel zu erweitern, können wir eine Sortierung implementieren, indem
wir eine Comparator
Klasse programmieren, in der diese Datum-Strings entsprechend
aufbereitet werden:
import java.util.*; import java.text.*; public class DateExample2 { static SimpleDateFormat sdFormatter = new SimpleDateFormat("dd.MM.yyyy"); static String[] dateStrings = { "25.03.2006", "12.07.2005", "18.12.2007" }; public static void main(String[] args) { Arrays.sort(dateStrings, new DateStringComparator()); for (String dateString: dateStrings) { System.out.println(dateString); } } static class DateStringComparator implements Comparator<String> { public int compare(String dateString1, String dateString2) { Date date1, date2; try { date1 = sdFormatter.parse(dateString1); date2 = sdFormatter.parse(dateString2); } catch (ParseException ex) { throw new RuntimeException(ex); } return date1.compareTo(date2); } } }
C:\temp>java DateExample2 12.07.2005 25.03.2006 18.12.2007
Zugegebenermaßen ist das letzte Beispiel nicht sehr glücklich gewählt, da es
bei der Sortierung von vielen Datum-Strings Unmengen an Ressourcen verbraucht,
weil jedes Mal die Strings neu geparst werden müssen. Sinnvoller wäre hier
sicherlich, die Datum-Strings in eine direkt vergleichbare Form
(z.B. JJJJMMTT
) umzuwandeln:
... static class DateStringComparator implements Comparator<String> { public int compare(String dateString1, String dateString2) { StringBuffer sb1 = new StringBuffer(dateString1.substring(6)) .append(dateString1.substring(3, 5)).append(dateString1.substring(0, 2)); StringBuffer sb2 = new StringBuffer(dateString2.substring(6)) .append(dateString2.substring(3, 5)).append(dateString2.substring(0, 2)); return sb1.toString().compareTo(sb2.toString()); } } ...
Instanzen der Klasse Date
selbst bieten keine Methoden an,
mit denen man beispielsweise die Differenz in Anzahl Tagen zueinander berechnen könnte.
Allerdings repräsentiert ein Date
-Objekt die Anzahl Millisekunden,
die seit dem 01.01.1970 0:00 Uhr vergangen sind, und mit diesen Anzahl Millisekunden
können dann Berechnungen vorgenommen werden, indem man die Anzahl Millisekunden
eines Tages als Konstante für Rechenoperationen heranzieht:
import java.util.*; import java.text.*; public class DateExample3 { public static void main(String[] args) throws ParseException { SimpleDateFormat sdFormatter = new SimpleDateFormat("dd.MM.yyyy"); long dayMillis = 24 * 60 * 60 * 1000; Date date1 = sdFormatter.parse("15.01.2008"); Date date2 = new Date(date1.getTime() + (30 * dayMillis)); System.out.println( sdFormatter.format(date1) + " + 30 Tage = " + sdFormatter.format(date2)); date1 = new Date(date2.getTime() - (60 * dayMillis)); System.out.println( sdFormatter.format(date2) + " - 60 Tage = " + sdFormatter.format(date1)); } }
C:\temp>java DateExample3 15.01.2008 + 30 Tage = 14.02.2008 14.02.2008 - 60 Tage = 16.12.2007
Falls Sie vorhaben, ein Datum über eine grafische Oberfläche erfassen zu lassen, bietet
sich die Verwendung eines JFormattedTextField
direkt an. Denn dieser GUI
Komponente kann zum einen als unterliegendes Datenmodell eine SimpleDateFormat
Instanz mit entsprechendem Eingabemuster mitgegeben werden und zum anderen sorgt das
JFormattedTextField
auch dafür, dass Eingaben nur basierend auf diesem Muster
zulässig sind:
import java.awt.*; import java.awt.event.*; import java.text.*; import java.util.*; import javax.swing.*; class DateExample4GUI extends JFrame { SimpleDateFormat sdF1 = new SimpleDateFormat("dd.MM.yyyy"); SimpleDateFormat sdF2 = new SimpleDateFormat("yyyy-MM-dd"); JFormattedTextField dateFTF; public DateExample4GUI() { getContentPane().setLayout(new BorderLayout()); JLabel dateLB = new JLabel(); dateLB.setText("Datum:"); getContentPane().add(dateLB, BorderLayout.WEST); dateFTF = new JFormattedTextField(sdF1); dateFTF.setValue(new Date()); getContentPane().add(dateFTF, BorderLayout.EAST); JButton saveBTN = new JButton(); saveBTN.setText("Save"); getContentPane().add(saveBTN, BorderLayout.SOUTH); saveBTN.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(null, sdF2.format(dateFTF.getValue())); } }); } } public class DateExample4 extends JApplet { JFrame guiFrame = new DateExample4GUI(); public void init() { setContentPane(guiFrame.getContentPane()); } public static void main(String[] args) { DateExample4 ex4 = new DateExample4(); ex4.guiFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); ex4.guiFrame.pack(); ex4.guiFrame.setVisible(true); } }
Abschließend soll noch anhand eines selbsterklärenden Beispiels die Java
GregorianCalendar
Klasse vorgestellt werden, die einige nützliche Informationen wie z.B. den Wochentag oder
die Jahreswoche, etc. zu einem Datum liefern kann:
import java.util.*; import java.text.*; public class DateExample5 { public static void main(String[] args) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); String birthDay = "17.01.1978"; String[] weekDays = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" }; Calendar cal = new GregorianCalendar(2008, Calendar.DECEMBER, 25); log("Weihnachten 2008"); log("Wochen Tag : " + weekDays[cal.get(Calendar.DAY_OF_WEEK) - 1]); log("Jahres Woche: " + cal.get(Calendar.WEEK_OF_YEAR)); log("Monats Woche: " + cal.get(Calendar.WEEK_OF_MONTH)); cal.setTime(sdf.parse(birthDay)); log("Geburtstag " + birthDay); log("Wochen Tag : " + weekDays[cal.get(Calendar.DAY_OF_WEEK) - 1]); log("Jahres Woche: " + cal.get(Calendar.WEEK_OF_YEAR)); log("Monats Woche: " + cal.get(Calendar.WEEK_OF_MONTH)); } static void log(String logString) { System.out.println(logString); } }
C:\temp>java DateExample5 Weihnachten 2008 Wochen Tag : Donnerstag Jahres Woche: 52 Monats Woche: 4 Geburtstag 17.01.1978 Wochen Tag : Dienstag Jahres Woche: 3 Monats Woche: 3
Copyright © 2003 Wöhrmann Softwareentwicklung - Höhenkirchen-Siegertsbrunn - Landkreis München