// Datum.java
package vererbung;
import java.util.Calendar;

/**
 * Datum ist ein Bauplan f&uuml;r Datumswerte.
 * Beispielprogramm zur Programmiertechnik 1, Teil 5.
 * Anders als in Teil 4 alle Instanzvariablen privat (Kapselung) und
 * deshalb zus&auml;tzlich gleichnamige Instanzmethoden zur Wertabfrage.
 * @author H.Drachenfels
 * @version 19.2.2024
 */
public final class Datum {
    private final int tag;
    private final int monat;
    private final int jahr;

    private Datum(int tag, int monat, int jahr) {
        this.tag = tag;
        this.monat = monat;
        this.jahr = jahr;
    }

    /**
     * Fabrikmethode, die ein value object mit dem angegebenen Datum liefert.
     * @param tag ist der Tag im Monat
     * @param monat ist der Monat im Jahr
     * @param jahr ist das Jahr
     * @return Referenz auf das value object
     */
    public static Datum valueOf(int tag, int monat, int jahr) {
        // Datum pruefen (stark vereinfacht)
        if (tag < 1 || tag > 31 || monat < 1 || monat > 12) {
            throw new IllegalArgumentException("ungueltiges Datum");
        }

        // value object erzeugen
        return new Datum(tag, monat, jahr);
    }

    /**
     * Fabrikmethode, die ein value object mit dem aktuellen Datum liefert.
     * @return Referenz auf das value object
     */
    public static Datum heute() {
        // Systemkalender ablesen
        Calendar c = Calendar.getInstance();

        // value object erzeugen
        return new Datum(c.get(Calendar.DAY_OF_MONTH),
                         c.get(Calendar.MONTH) + 1,
                         c.get(Calendar.YEAR));
    }

    /**
     * Liefert den Tag im Monat.
     * @return Tag im Monat als Zahl 1 bis 31
     */
    public int tag() {
        return this.tag;
    }

    /**
     * Liefert den Monat.
     * @return Monat als Zahl 1 bis 12
     */
    public int monat() {
        return this.monat;
    }

    /**
     * Liefert das Jahr.
     * @return Jahr
     */
    public int jahr() {
        return this.jahr;
    }

    @Override
    public String toString() {
        return String.format("%d-%02d-%02d", this.jahr, this.monat, this.tag);
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Datum) {
            Datum that = (Datum) o;
            return this.tag == that.tag
                   && this.monat == that.monat
                   && this.jahr == that.jahr;
        }

        return false;
    }

    @Override
    public int hashCode() {
        return (this.jahr << 9) + (this.monat << 5) + this.tag;
    }
}

