Die Klasse Fraction enthält nur zwei Eigenschaften, den Zähler (long
nominator
) und den Nenner (long denominator
). Der Bruch
wird im Konstruktor automatisch gekürzt, dazu wird mit Hilfe der Funktion
long gcd(long,long)
wird der größte gemeinsame Teiler
ermittelt. Die möglichen Ergebnisse von compareTo(Fraction) wurden in drei
statische Konstanten (IS_SMALLER = -1, IS_EQUAL = 0, IS_GREATER = 1
)
gepackt.
Das Programm wurde ausführlich im Source dokumentiert.
/** * Softwareentwicklung I - Exercise 8/1. * Fraction. Allows mathematical operations with fractions. * In-source comments are followed by the described code. * * @author Daniel Brunthaler (0255054) * @version 1.0 */ public final class Fraction { private long nominator; private long denominator; // constants returned by compareTo(Fraction) public static final int IS_SMALLER = -1, IS_EQUAL = 0, IS_GREATER = 1; /** * Constructs a fraction nom/1. * @param nom nominator. */ public Fraction(long nom) { this(nom,1); } /** * Constructs a Fraction nom/denom. If denom = 0 the denominator is set * to 1. If denom is negative, the nominator is multiplied with -1. The * fraction is automatically canceled down if possible. * @param nom nominator. * @param denom denominator. */ public Fraction(long nom, long denom) { super(); if (denom == 0) denom = 1; if (denom < 0) { nom *= -1; denom *= -1; } long gcd = gcd(nom,denom); this.nominator = nom / gcd; this.denominator = denom / gcd; } /** * Nominator of fraction. * @return nominator of fraction. */ protected long getNom() { return nominator; } /** * Denominator of fraction. * @return denominator of fraction. */ protected long getDenom() { return denominator; } /** * Reciprocal of this fraction. * @return reciprocal of this fraction. */ public Fraction reciprocal() { return new Fraction(getDenom(),getNom()); } /** * Float value of this fraction. * @return float value of this fraction. */ public float toFloat() { float x = nominator, y = denominator; return x/y; } /** * Double value of this fraction. * @return double value of this fraction. */ public double toDouble() { double x = nominator, y = denominator; return x/y; } /** * Greatest common divisor of a and b. * @param a value. * @param b value. * @return greatest common divisor of a and b. */ private static final long gcd(long a, long b) { a = Math.abs(a); b = Math.abs(b); if (a == 0) return b; if (b == 0) return a; while (a != b) if (a > b) a = a - b; else b = b - a; return a; } /** * Adds fraction a to this fraction. * @param a which should be added. * @return result of the addition as Fraction. */ public Fraction add(Fraction a) { long nom, denom; if (a.getDenom() != getDenom()) { // an/ad + bn/bd = (an*bd + bn*ad)/(ad*bd) denom = a.getDenom() * getDenom(); nom = a.getNom() * getDenom() + getNom() * a.getDenom(); } else { denom = getDenom(); nom = getNom() + a.getNom(); } return new Fraction(nom,denom); } /** * Adds a/1 to this fraction. * @param a which should be added as a/1. * @return result of the addition as Fraction. */ public Fraction add(long a) { return add(new Fraction(a)); } /** * Subtracts given fraction from this fraction. * @param a which should be subtracted * @return result of the subtraction. */ public Fraction subtract(Fraction a) { // b - a = b + (-a) => Fraction.add(-a) Fraction a_negative = new Fraction(- a.getNom(),a.getDenom()); return add(a_negative); } /** * Subtracts a/1 from this fraction. * @param a which should be subtracted. * @return result of the subtraction. */ public Fraction subtract(long a) { return subtract(new Fraction(a)); } /** * Multiplies this fraction with given fraction. * @param a which should this fraction multiplied with. * @return result of multiplication. */ public Fraction multiply(Fraction a) { return new Fraction(getNom() * a.getNom(), getDenom() * a.getDenom()); } /** * Multiplies this fraction with a/1. * @param a which should this fraction multiplied with. * @return result of the multiplication. */ public Fraction multiply(long a) { return multiply(new Fraction(a)); } /** * Divides this fraction by a. * @param a which should this fraction divided by. * @return result of the division. */ public Fraction divide(Fraction a) { // a/x / b/y = a/x * y/b return multiply(a.reciprocal()); } /** * Divides this fraction by a/1. * @param a which should this fraction divided by. * @return result of the division. */ public Fraction divide(long a) { // a/x / b/1 = a/x * 1/b return multiply((new Fraction(a)).reciprocal()); } /** * Compares this fraction to given fraction b. * @param b fraction which should this fraction compared with. * @return Fraction.IS_SMALLER if b is smaller, Fraction.IS_GREATER * if b is greater or Fraction.IS_EQUAL if b is equal. */ public int compareTo(Fraction b) { // an/ad == bn/bd ? => an*bd == bn*ad ? (=> same denominator) long a_nom = getNom() * b.getDenom(); long b_nom = b.getNom() * getDenom(); if (a_nom == b_nom) return IS_EQUAL; else if (a_nom < b_nom) return IS_SMALLER; else return IS_GREATER; } /** * Compares this fraction to b/1. * @param b (b/1) which should this fraction compared with. * @return Fraction.IS_SMALLER if b/1 is smaller, Fraction.IS_GREATER * if b/1 is greater or Fraction.IS_EQUAL if b/1 is equal. */ public int compareTo(long b) { return compareTo(new Fraction(b)); } /** * Checks if b is a Fraction and returns true if it is equal * this fraction. * @param b which this Fraction should be compared to. * @return true if b is a Fraction and equal this Fraction. */ public boolean equals(Object b) { if (b.getClass() == Fraction.class) { Fraction bf = (Fraction) b; if (bf.getNom() == getNom() && bf.getDenom() == getDenom()) { // nominator and denominator of both fractions are equal return true; } } return false; } /** * Returns the fraction in a String "/ ". If the * denominator = 1 it returns only " ". */ public String toString() { if (getDenom() == 1) return getNom() + ""; else return getNom() + "/" + getDenom(); } }
Zum Testen wurde die Klasse FractionTest
entwickelt, welche
das Testframework junit (http://junit.org) verwendet. Alle darin enthaltenen
Methoden testXYZ()
werden im Testlauf automatisch ausgeführt.
In den Testmethoden wiederum befinden sich außer in testCreation()
assert-Methoden, welche Ergebnisse von Methoden der Klasse Fraction überprüfen
(meist in der Form assertEquals(exceptedValue,actualValue)
). Das
Programm wurde ausführlich kommentiert.
(Das Testen mit junit erspart unter anderem das mehrmalige Durchsehen von Testausgaben
oder auch das aufwendige Entwickeln einer Ein-/Ausgabe-Testapplikation)
Testplan
Eingabe | Erwartete Ausgabe | Zweck | In Testmethode |
---|---|---|---|
new Fraction(1,2).toString() | "1/2" | Fraction Objekt erzeugen | testCreation() |
new Fraction(2,0).toString() | "2" | Fraction Objekt erzeugen | testCreation() |
new Fraction(-1,2).toString() | "-1/2" | Fraction Objekt erzeugen | testCreation() |
new Fraction(1,-2).toString() | "-1/2" | Fraction Objekt erzeugen | testCreation() |
new Fraction(-1,-2).toString() | "1/2" | Fraction Objekt erzeugen | testCreation() |
new Fraction(3,10).equals(new Fraction(6,20)) | True | Test der Methode Fraction.equals(Fraction) | testEquals() |
new Fraction(-17,19).equals(new Fraction(-19,17)) | False | Test der Methode Fraction.equals(Fraction) | testEquals() |
new Fraction(1,-3).reciprocal() | new Fraction(-3) | Test der Methode Fraction.reciprocal() | testReciprocal() |
new Fraction(17,19).reciprocal() | new Fraction(19/17) | Test der Methode Fraction.reciprocal() | testReciprocal() |
new Fraction(1,2).toFloat() | 0.5 | Test der Methode Fraction.toFloat() | testToFloat() |
new Fraction(1,2).toDouble() | 0.5 | Test der Methode Fraction.toDouble() | testToDouble() |
new Fraction(2,3).add(new Fraction(3,5)) | new Fraction(19,15) | Test der Methode Fraction.add(Fraction) | testAdd() |
new Fraction(2,3).add(1) | new Fraction(5,3) | Test der Methode Fraction.add(long) | testAdd() |
new Fraction(5,8).subtract(new Fraction(1,7)) | new Fraction(27,56) | Test der Methode Fraction.subtract(Fraction) | testSubtract() |
new Fraction(5,8).subtract(1) | new Fraction(-3,8) | Test der Methode Fraction.subtract(long) | testSubtract() |
new Fraction(-3,4).multiply(new Fraction(7,6)) | new Fraction(-21,24) | Test der Methode Fraction.multiply(Fraction) | testMultiply() |
new Fraction(-3,4).multiply(-2) | new Fraction(6,4) | Test der Methode Fraction.multiply(long) | testMultiply() |
new Fraction(4,6).divide(new Fraction(1,8)) | new Fraction(16,3) | Test der Methode Fraction.divide(Fraction) | testDivide() |
new Fraction(4,6).divide(-2) | new Fraction(-1,3) | Test der Methode Fraction.divide(long) | testDivide() |
new Fraction(1,6).compareTo(new Fraction(-5,6)) | Fraction.IS_GREATER | Test der Methode Fraction.compareTo(Fraction) | testCompareTo() |
new Fraction(-5,6).compareTo(new Fraction(1,6)) | Fraction.IS_SMALLER | Test der Methode Fraction.compareTo(Fraction) | testCompareTo() |
new Fraction(1,6).compareTo(new Fraction(1,6)) | Fraction.IS_EQUAL | Test der Methode Fraction.compareTo(Fraction) | testCompareTo() |
new Fraction(-5,6).compareTo(0) | Fraction.IS_SMALLER | Test der Methode Fraction.compareTo(long) | testCompareTo() |
new Fraction(1,6).compareTo(-2) | Fraction.IS_GREATER | Test der Methode Fraction.compareTo(long) | testCompareTo() |
new Fraction(-6,6).compareTo(-1) | Fraction.IS_EQUAL | Test der Methode Fraction.compareTo(long) | testCompareTo() |
Testprogramm
import junit.framework.*; /** * Softwareentwicklung I - Exercise 8/1. * Test class for Fraction, uses junit. * * The following tests are included: * - testCreation - Creates and prints certain fractions to System.out. * - testEquals - Tests boolean Fraction.equals(Object) by * comparing two equal Fractions and two non equal Fractions. * - testReciprocal - Tests Fraction Fraction.reciprocal(Fraction). * - testToFloat - Tests float Fraction.toFloat(). * - testToDouble - Tests double Fraction.toDouble(). * - testAdd - Tests Fraction Fraction.add(Fraction) and * Fraction Fraction.add(long). * - testSubtract - Tests Fraction Fraction.add(Fraction) and * Fraction Fraction.add(long). * - testMultiply - Tests Fraction Fraction.multiply(Fraction) and * Fraction Fraction.multiply(long). * - testDivide - Tests Fraction Fraction.divide(Fraction) and * Fraction Fraction.divide(long). * - testCompareTo - Tests int Fraction.compareTo(Fraction) and * int Fraction.compareTo(long). * * In-source comments are followed by the described code. * * @see Fraction, http://junit.org * @author Daniel Brunthaler (0255054) * @version 1.0 */ public class FractionTest extends TestCase { public FractionTest(String name) { super(name); } public void testCreation() { System.out.println( "test creation of Fraction objects and Fraction.toString()"); Fraction a; a = new Fraction(1,2); System.out.println("new Fraction(1,2) = " + a.toString()); a = new Fraction(2,0); System.out.println("new Fraction(2,0) = " + a.toString()); a = new Fraction(-1,2); System.out.println("new Fraction(-1,2) = " + a.toString()); a = new Fraction(1,-2); System.out.println("new Fraction(1,-2) = " + a.toString()); a = new Fraction(-1,-2); System.out.println("new Fraction(-1,-2) = " + a.toString()); } public void testEquals() { System.out.println("test Fraction.equals(Fraction)"); assertTrue( // 3/10 is equal 6/20 new Fraction(3,10).equals(new Fraction(6,20))); assertEquals(false, // -17/19 is not equal -19/17 new Fraction(-17,19).equals(new Fraction(-19,17))); } public void testReciprocal() { System.out.println("test Fraction.reciprocal()"); Fraction a = new Fraction(1,-3); // reciprocal(-1/3) = -3 assertEquals(new Fraction(-3),a.reciprocal()); a = new Fraction(17,19); // reciprocal(17/19) = 19/17 assertEquals(new Fraction(19,17),a.reciprocal()); } public void testToFloat() { System.out.println("test Fraction.toFloat()"); Fraction a = new Fraction(1,2); float x = new Float(0.5).floatValue(); assertEquals(x,a.toFloat(),0); // 1/2 = 0.5 } public void testToDouble() { System.out.println("test Fraction.toDouble()"); Fraction a = new Fraction(1,2); assertEquals(0.5,a.toDouble(),0); // 1/2 = 0.5 } public void testAdd() { System.out.println( "test Fraction.add(Fraction) and Fraction.add(long)"); Fraction a = new Fraction(2,3), b = new Fraction(3,5); assertEquals(new Fraction(19,15),a.add(b)); // 2/3 + 3/5 = 19/15 assertEquals(new Fraction(5,3),a.add(1)); // 2/3 + 1 = 5/3 } public void testSubtract() { System.out.println( "test Fraction.subtract(Fraction) and Fraction.subtract(long)"); Fraction a = new Fraction(5,8), b = new Fraction(1,7); assertEquals(new Fraction(27,56),a.subtract(b)); // 5/8 - 1/7 = 27/56 assertEquals(new Fraction(-3,8),a.subtract(1)); // 5/8 - 1 = -3/8 } public void testMultiply() { System.out.println( "test Fraction.multiply(Fraction) and Fraction.multiply(long)"); Fraction a = new Fraction(-3,4), b = new Fraction(7,6); // -3/4 * 7/6 = -21/24 assertEquals(new Fraction(-21,24),a.multiply(b)); assertEquals(new Fraction(6,4),a.multiply(-2)); // -3/4 * -2 = 6/4 } public void testDivide() { System.out.println( "test Fraction.divide(Fraction) and Fraction.divide(long)"); Fraction a = new Fraction(4,6), b = new Fraction(1,8); assertEquals(new Fraction(16,3),a.divide(b)); // 4/6 / 1/8 = 16/3 assertEquals(new Fraction(-1,3),a.divide(-2)); // 4/6 / -2 = -1/3 } public void testCompareTo() { System.out.println("test Fraction.compareTo(Fraction) " + "and Fraction.compareTo(long)"); Fraction a = new Fraction(-5,6), b = new Fraction(1,6), c = new Fraction(1,6); assertEquals(Fraction.IS_GREATER,b.compareTo(a)); assertEquals(Fraction.IS_SMALLER,a.compareTo(b)); assertEquals(Fraction.IS_EQUAL,b.compareTo(c)); c = a.subtract(b); // c = -5/6 - 1/6 = -6/6 = -1 assertEquals(Fraction.IS_SMALLER,a.compareTo(0)); assertEquals(Fraction.IS_GREATER,b.compareTo(-2)); assertEquals(Fraction.IS_EQUAL,c.compareTo(-1)); } public static Test suite() { return new TestSuite(FractionTest.class); } public static void main(String[] args) { junit.textui.TestRunner.run (suite()); } }
Hardcopy
Graphische Darstellung der Klassenhierarchie
Die Klasse DateFormatter
ist eine abstrakte Klasse und gibt die
Methoden vor, welche von den erbenden Klassen implementiert werden müssen.
Die Methode formatDate(...)
enthält eine Defaultformatierung
(deutsch) und muss von der erbenden Klasse übersteuert werden, wenn das
Format vom deutschen verschieden ist. Die regionalen Klassen wie der DateFormatter
für Österreich übersteuern schließlich nur mehr die Methoden,
welche für die Implementierung der regionalen Details notwendig sind (bspw.
in Österreich Methode month(int)
).
Das Programm wurde ausführlich im Source dokumentiert.
/** * Softwareentwicklung I - Exercise 8/2. * DateFormatter. * In-source comments are followed by the described code. * * @see DateFormatterGerman, DateFormatterEnglish, DateFormatterFrench * @see DateFormatterSpanish * @author Daniel Brunthaler (0255054) * @version 1.0 */ public abstract class DateFormatter { /** * @see java.lang.Object#Object() */ public DateFormatter() { super(); } /** * Identifier for a certain day of the week. * @param dayOfWeek number of the day (1-7). * @return identifier for given day of the week. */ protected abstract String dayOfWeek(int dayOfWeek); /** * Identifier for a certain month. * @param month for which the identifier should be returned. * @return identifier of given month. */ protected abstract String month(int month); /** * Name of the language for which the DateFormatter is designated. * @return language Name for which the DateFormatter is designated. */ public abstract String getLanguageName(); /** * Formats the given date. Default format is * ', . ' (german format). * @param dayOfWeek number of the day of the week (1 - 7). * @param day of date (1 - 31). * @param month of date (1 - 12). * @param year of date. * @return formatted date. */ public String formatDate(int dayOfWeek, int day, int month, int year) { return dayOfWeek(dayOfWeek) + ", " + day + ". " + month(month) + " " + year; } } /** * Softwareentwicklung I - Exercise 8/2. * DateFormatter for german regions. * @see DateFormatterGermanNorth, DateFormatterGermanAustria */ public class DateFormatterGerman extends DateFormatter { private static final String[] DAYS_OF_WEEK = {"Montag","Dienstag","Mittwoch","Donnerstag","Freitag", "Samstag","Sonntag"}; private static final String[] MONTHS = {"Januar","Februar","März","April","Mai","Juni","Juli","August", "Oktober","November","Dezember"}; private static final String LANGUAGE_NAME = "Deutsch"; public DateFormatterGerman() { super(); } /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return LANGUAGE_NAME; } /** * @see DateFormatter#dayOfWeek() */ protected String dayOfWeek(int dayOfWeek) { return DAYS_OF_WEEK[dayOfWeek - 1]; } /** * @see DateFormatter#month() */ protected String month(int month) { return MONTHS[month - 1]; } } /** * Softwareentwicklung I - Exercise 8/2. * Dateformatter for north germany. */ public class DateFormatterGermanNorth extends DateFormatterGerman { private final String SATURDAY_IN_NORTHGERMANY = "Sonnabend"; private final String LANGUAGE_NAME = "Norddeutschland"; /** * 'Samstag' is called in north germany 'Sonnabend'. * @see DateFormatter#dayOfWeek(int) */ protected String dayOfWeek(int dayOfWeek) { if (dayOfWeek == 6) return SATURDAY_IN_NORTHGERMANY; else return super.dayOfWeek(dayOfWeek); } /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return super.getLanguageName() + " (" + LANGUAGE_NAME + ")"; } } /** * Softwareentwicklung I - Exercise 8/2. * DateFormatter for Austria. */ public class DateFormatterGermanAustria extends DateFormatterGerman { private final String JANUARY_IN_AUSTRIA = "Jänner"; private final String LANGUAGE_NAME = "Österreich"; /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return super.getLanguageName() + " (" + LANGUAGE_NAME + ")"; } /** * 'Januar' is called in Austria 'Jänner'. * @see DateFormatter#month(int) */ protected String month(int month) { if (month == 1) return JANUARY_IN_AUSTRIA; else return super.month(month); } } /** * Softwareentwicklung I - Exercise 8/2. * DateFormatter for english regions. * * @see DateFormatterEnglishUSA */ public class DateFormatterEnglish extends DateFormatter { private static final String[] DAYS_OF_WEEK = {"Monday","Tuesday","Wednesday","Thursday","Friday", "Saturday","Sonday"}; private static final String[] MONTHS = {"January","February","March","April","May","June","July","August", "October","November","December"}; private static final String LANGUAGE_NAME = "Englisch"; /** * @see DateFormatter#dayOfWeek(int) */ protected String dayOfWeek(int dayOfWeek) { return DAYS_OF_WEEK[dayOfWeek - 1]; } /** * @see DateFormatter#month(int) */ protected String month(int month) { return MONTHS[month - 1]; } /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return LANGUAGE_NAME; } /** * @see DateFormatter#formatDate(int, int, int, int) */ public String formatDate(int dayOfWeek, int day, int month, int year) { return dayOfWeek(dayOfWeek) + " " + day + " " + month(month) + " " + year; } } /** * Softwareentwicklung I - Exercise 8/2. * DateFormatter for United States. */ public class DateFormatterEnglishUSA extends DateFormatterEnglish { /** * Formatting in USA different from general english. * @see DateFormatter#formatDate(int, int, int, int) */ public String formatDate(int dayOfWeek, int day, int month, int year) { return dayOfWeek(dayOfWeek) + ", " + month(month) + " " + day + ", " + year; } } /** * Softwareentwicklung I - Exercise 8/2. * French DateFormatter. */ public class DateFormatterFrench extends DateFormatter { private static final String[] DAYS_OF_WEEK = {"lundi","mardi","mercredi","jeudi","vendredi", "samedi","dimanche"}; private static final String[] MONTHS = {"janvier","février","mars","avril","mai","juin","juillet","août", "septembre","octobre","novembre","décembre"}; private static final String LANGUAGE_NAME = "Französisch"; /** * @see DateFormatter#dayOfWeek(int) */ protected String dayOfWeek(int dayOfWeek) { return DAYS_OF_WEEK[dayOfWeek - 1]; } /** * @see DateFormatter#month(int) */ protected String month(int month) { return MONTHS[month - 1]; } /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return LANGUAGE_NAME; } /** * @see DateFormatter#formatDate(int, int, int, int) */ public String formatDate(int dayOfWeek, int day, int month, int year) { return dayOfWeek(dayOfWeek) + " " + day + " " + month(month) + " " + year; } } /** * Softwareentwicklung I - Exercise 8/2. * Spanish DateFormatter. */ public class DateFormatterSpanish extends DateFormatter { private static final String[] DAYS_OF_WEEK = {"lunes","martes","miércoles","jueves","viernes", "sábado","domingo"}; private static final String[] MONTHS = {"enero","febrero","marzo","abril","mayo","junio","julio","agosto", "septiembre","octubre","noviembre","diciembre"}; private static final String LANGUAGE_NAME = "Spanisch"; /** * @see DateFormatter#dayOfWeek(int) */ protected String dayOfWeek(int dayOfWeek) { return DAYS_OF_WEEK[dayOfWeek - 1]; } /** * @see DateFormatter#month(int) */ protected String month(int month) { return MONTHS[month - 1]; } /** * @see DateFormatter#getLanguageName() */ public String getLanguageName() { return LANGUAGE_NAME; } /** * @see DateFormatter#formatDate(int, int, int, int) */ public String formatDate(int dayOfWeek, int day, int month, int year) { return dayOfWeek(dayOfWeek) + ", " + day + " de " + month(month) + " de " + year; } }
Zum Testen wurde wie in der Aufgabenstellung angewiesen, das Prg. DateFormats verwendet und entsprechend angepasst.
Testprogramm
/** * Softwareentwicklung I - Exercise 8/2. * Test program for DateFormatter and its subclasses. * In-source comments are followed by the described code. * * @author ? */ public class DateFormats { static DateFormatter fmt[]={ // ... hier an die verfügbaren Sprachen anpassen ... new DateFormatterGerman(),new DateFormatterGermanNorth(), new DateFormatterGermanAustria(),new DateFormatterEnglish(), new DateFormatterEnglishUSA(),new DateFormatterFrench(), new DateFormatterSpanish() }; static void printDate(int dayOfWeek,int day,int month,int year) { for (int i=0; i < fmt.length; i++) { IO.write("["+fmt[i].getLanguageName()+"] "); IO.writeLn(fmt[i].formatDate(dayOfWeek,day,month,year)); } } public static void main(String[] args) { int dayOfWeek,day,month,year; IO.write("Tag: "); day=IO.readInt(); IO.write("Monat: "); month=IO.readInt(); IO.write("Jahr: "); year=IO.readInt(); IO.writeLn(); dayOfWeek=new java.util.GregorianCalendar(year,month-1,day).get(java.util.Calendar.DAY_OF_WEEK)-1; if (dayOfWeek==0) dayOfWeek=7; printDate(dayOfWeek,day,month,year); } }
Testplan
Eingabe | Erwartete Ausgabe | Zweck |
---|---|---|
Tag: 11, Monat: 1, Jahr: 2003 | siehe Aufgabenstellung | Test analog dem Beispiel in der Aufgabenstellung |
Tag: 15, Monat: 2, Jahr: 2003 | Freitag, 14. Februar 2003 etc. | Anderer Wochentag, anderes Monat, |
Tag: 2, Monat: 3, Jahr: 2004 | Dienstag, 2. März 2004 etc. | Anderer Wochentag, anderes Monat, anderes Jahr |
Hardcopy