/**
 * Diese Klasse erzeugt Datumsobjekte.
 * Das Datum besteht aus einem Jahr, einem Monat und einem Tag.
 * Die Zeitrechnung, in welcher das Datum interpretiert werden muß, ist nicht
 * definiert.
 * Schaltjahre werden nicht gesondert berücksichtigt, so daß der 29. Februar
 * für jede Jahreszahl erlaubt ist.<br>
 * Für die textuelle Repräsentation werden zwei Formate unterstützt:
 * <dl>
 * <dt>deutsches Datumsformat
 * <dd>&lt;tag&gt;.&lt;monat&gt;.&lt;jahr&gt;
 * <dt>englisches Datumsformat
 * <dd>&lt;monat&gt;/&lt;tag&gt;/&lt;jahr&gt;
 * </dl>
 * @author bisanz
 * @version 1.0
 */
public class Date {
  /** Das Jahr. */
  private int year;
  /** Der Monat. Werte aus [1,12] sind zulässig. */
  private int month;
  /** Der Tag. Werte aus [1,31], [1,30] oder [1,29] sind in Abhängigkeit vom
      Monat zulässig. */
  private int day;
  /** Konstante für deutsche Datumskonvention. */
  public static final int DE = 0;
  /** Konstante für englische Datumskonvention. */
  public static final int EN = 1;
  /**
   * Der Konstruktor.
   * @param year Das Jahr.
   * @param month Der Monat. Werte aus [1,12] sind zulässig.
   * @param day Der Tag. In Abhängigkeit von <code>month</code> sind folgende
   * Werte zulässig:
   * <code>month</code> aus {1,3,5,7,8,10,12}: [1,31].
   * <code>month</code> aus {4,6,9,11}: [1,30].
   * <code>month</code> aus {2}: [1,29].
   * @throws IllegalArgumentException Wird geworfen, falls <code>month</code>
   * oder <code>day</code> einen unzulässigen Wert enthalten.
   */
  public Date (int year, int month, int day) throws IllegalArgumentException {
    // Werte prüfen ...
    // Untergrenze für den Tag prüfen
    boolean illegalDay = day < 1;
    switch (month) {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
      // Obergrenze Tag für Monate mit 31 Tagen prüfen
      illegalDay = illegalDay || (day > 31);
      break;
    case 4: case 6: case 9: case 11:
      // Obergrenze Tag fuer Monate mit 30 Tagen prüfen
      illegalDay = illegalDay || (day > 30);
      break;
    case 2:
      // Obergrenze Tag fuer Monate mit 29 Tagen prüfen
      illegalDay = illegalDay || (day > 29);
      break;
    default:
      // hierher gelangen wir, wenn die Monatsangabe nicht ok ist
      throw new IllegalArgumentException("Ungültiger Monat: " + month);
    }
    if (illegalDay) {
      // hierher gelangen wir, wenn die Tagesangabe nicht ok ist
      throw new IllegalArgumentException("Ungültiger Tag: " + day);
    }
    // alle Werte ok, dann Attribute initialisieren
    this.year = year;
    this.month = month;
    this.day = day;
  }
  /**
   * Gibt den Tag zurück.
   * @return Der Tag.
   */
  public int getDay () { return day; }
  /**
   * Gibt den Monat zurück.
   * @return Der Monat.
   */
  public int getMonth () { return month; }
  /**
   * Gibt das Jahr zurück.
   * @return Das Jahr.
   */
  public int getYear () { return year; }
  /**
   * Gibt eine Zeichenkettenrepräsentation des Datums zurück.
   * @param format Das Ausgabeformat. Zulässige Werte sind:
   * <code>DE</code> für deutsches Datumsformat.
   * <code>EN</code> für englisches Datumsformat.
   * @return Die Zeichenkettenrepräsentation.
   * @throws IllegalArgumentException Wird geworfen, falls ein ungültiges
   * Format angegeben ist.
   */
  public String toString (int format) throws IllegalArgumentException {
    switch (format) {
    case DE: /* deutsches Datumsformat */ return toStringDE();
    case EN: /* englisches Datumsformt */ return toStringEN();
    default:
      // kein bekanntes Format
      throw new IllegalArgumentException ("Unbekanntes Format.");
    }
  }
  /** Gibt eine Zeichenkettenrepräsentation des Datums im deutschen
      Datumsformat zurück. */
  private String toStringDE () {
    // <tag>.<monat>.<jahr>
    return day + "." + month + "." + year;
  }
  /** Gibt eine Zeichenkettenrepräsentation des Datums im englischen
      Datumsformat zurück. */
  private String toStringEN () {
    // <monat>/<tag>/<jahr>
    return month + "/" + day + "/" + year%100;
  }
}
