public class Date {

    private int jour, mois, annee;

    static private boolean estBissextile(int annee) {
        return (annee % 4 == 0 && annee % 100 != 0) || (annee % 400 == 0);
    }
    static private int nbJourMois(int mois, int annee) {
        switch (mois) {
            case 1 : case 3 : case 5 :
            case 7 : case 8 : case 10 : case 12 : return 31;
            case 4 : case 6 : case 9 : case 11  : return 30;
            case 2 :
                if (estBissextile(annee)) return 29;
                else                     return 28;
            default: return -1;
        }
    }

    public Date(int j, int m, int a) {
        this.jour = j;
        this.mois = m;
        this.annee = a;
        if (mois <= 0 || mois > 12
            || jour <= 0 || jour > nbJourMois(mois, annee))
            throw new IllegalArgumentException("date incorrecte");

    }

    public final boolean equals(Object other)
    {
        if (!(other instanceof Date))
            return false;
        Date a = (Date) other;
        return (this.jour == a.jour)
                && (this.mois == a.mois) && (this.annee == a.annee);
    }

    public String toString () {
        return String.format("%02d/%02d/%04d", this.jour, this.mois, this.annee);
    }

    /** Avance une Date au lendemain **/
    public void avance() { avance(1); }
    /** Avance une Date de n jours **/
    public void avance(int n) {
        jour += n;
        while (jour > nbJourMois(mois, annee)) {
            jour -= nbJourMois(mois, annee);
            mois++;
            if (mois == 13) {
                mois = 1;
                annee++;
            }
        }
    };

    public int ordinal() {
        int res = 0;
        for (int a = 1; a < annee; a++)
            res += 365 + (estBissextile(a) ? 1 : 0);
        for (int m = 1; m < mois; m++)
            res += nbJourMois(m, annee);
        res += jour;
        return res;
    }

    public int jourSemaine() { return (ordinal() + 6) % 7; }

    private final static String[] jours = {"lundi", "mardi", "mercredi",
        "jeudi", "vendredi", "samedi", "dimanche"};

    public String nomJour() { return jours[jourSemaine()]; }

    public boolean estAvant(Date autre) {
        return (this.annee < autre.annee)
                || (this.annee == autre.annee &&
                    ((this.mois < autre.mois) ||
                     (this.mois == autre.mois && this.jour < autre.jour)));
    }

    public static Date parseDate(String s) {
        int cut1 = s.indexOf('/');
        int cut2 = s.indexOf('/', cut1+1);
        int jour = Integer.parseInt(s.substring(0, cut1));
        int mois = Integer.parseInt(s.substring(cut1+1, cut2));
        int annee = Integer.parseInt(s.substring(cut2+1, s.length()));
        return new Date(jour, mois, annee);
    }

}
