163 votes

Comment calculer l'âge de quelqu'un en Java ?

Je veux retourner un âge en années sous la forme d'un int dans une méthode Java. Ce que j'ai maintenant est le suivant où getBirthDate() renvoie un objet Date (avec la date de naissance ;-)) :

public int getAge() {
    long ageInMillis = new Date().getTime() - getBirthDate().getTime();

    Date age = new Date(ageInMillis);

    return age.getYear();
}

Mais comme getYear() est déprécié, je me demande s'il existe une meilleure façon de procéder ? Je ne suis même pas sûr que cela fonctionne correctement, puisque je n'ai pas (encore) de tests unitaires en place.

0 votes

J'ai changé d'avis à ce sujet : l'autre question n'a qu'une approximation des années entre les dates, pas un âge vraiment correct.

0 votes

Étant donné qu'il renvoie un int, pouvez-vous préciser ce que vous entendez par un âge "correct" ?

2 votes

La différence entre date et calendrier est un concept fondamental que l'on peut glaner en lisant la documentation Java. Je ne comprends pas pourquoi cela a été autant upvoted.

190voto

duffymo Points 188155

Votre exemple n'est PAS la bonne façon de procéder.

Jetez un coup d'œil à ce .

Calendar dob = Calendar.getInstance();  
dob.setTime(dateOfBirth);  
Calendar today = Calendar.getInstance();  
int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);  
if (today.get(Calendar.MONTH) < dob.get(Calendar.MONTH)) {
  age--;  
} else if (today.get(Calendar.MONTH) == dob.get(Calendar.MONTH)
    && today.get(Calendar.DAY_OF_MONTH) < dob.get(Calendar.DAY_OF_MONTH)) {
  age--;  
}

La bibliothèque JODA datetime propose de jolis calculs d'intervalles. Essayez-le.

10 votes

La comparaison DAY_OF_YEAR peut conduire à un résultat erroné lorsqu'il s'agit d'années bissextiles.

1 votes

La variable dateOfBirth doit être un objet Date. Comment puis-je créer un objet Date avec la date de naissance ?

0 votes

Compte tenu du fait que nous avons 9 ans, et dans le cas où Java 8 serait utilisé, ce devrait être la solution à utiliser.

177voto

Brian Agnew Points 143181

Vérifiez Joda Joda, qui simplifie les calculs de date et d'heure (Joda est également la base de la nouvelle API standard de date et d'heure de Java, vous apprendrez donc une API qui sera bientôt standard).

EDIT : Java 8 aura quelque chose de très similaire et vaut la peine d'être vérifiée.

par exemple

LocalDate birthdate = new LocalDate (1970, 1, 20);
LocalDate now = new LocalDate();
Years age = Years.yearsBetween(birthdate, now);

qui est aussi simple que possible. Le matériel Java actuel est (comme vous l'avez identifié) quelque peu inintuitif.

2 votes

@HoàngLong : Extrait des JavaDocs : "Cette classe ne représente pas un jour, mais l'instant milliseconde à minuit. Si vous avez besoin d'une classe qui représente le jour entier, alors un Intervalle ou un LocalDate peuvent être plus appropriés." Nous avons vraiment faire veulent représenter une date ici.

0 votes

Si vous voulez le faire de la manière suggérée par @JohnSkeet, c'est comme ceci : Years age = Years.yearsBetween(new LocalDate(getBirthDate()), new LocalDate()) ;

0 votes

Je ne sais pas. pourquoi J'ai utilisé DateMidnight, et je note maintenant qu'il est déprécié. J'ai changé pour utiliser LocalDate

43voto

cletus Points 276888
Calendar now = Calendar.getInstance();
Calendar dob = Calendar.getInstance();
dob.setTime(...);
if (dob.after(now)) {
  throw new IllegalArgumentException("Can't be born in the future");
}
int year1 = now.get(Calendar.YEAR);
int year2 = dob.get(Calendar.YEAR);
int age = year1 - year2;
int month1 = now.get(Calendar.MONTH);
int month2 = dob.get(Calendar.MONTH);
if (month2 > month1) {
  age--;
} else if (month1 == month2) {
  int day1 = now.get(Calendar.DAY_OF_MONTH);
  int day2 = dob.get(Calendar.DAY_OF_MONTH);
  if (day2 > day1) {
    age--;
  }
}
// age is now correct

0 votes

Oui, la classe de calendrier est terrible. Malheureusement, au travail, je dois parfois l'utiliser :/. Merci Cletus d'avoir posté ceci

1 votes

Remplacez Calendar.MONTH et Calendar.DAY_OF_MONTH par Calendar.DAY_OF_YEAR et ce sera au moins un peu plus propre.

0 votes

@Tobbbe Si vous êtes né le 1er mars d'une année bissextile, votre anniversaire est le 1er mars de l'année suivante, et non le 2ème. DAY_OF_YEAR ne fonctionnera pas.

20voto

Farhan Munir Points 61
/**
 * This Method is unit tested properly for very different cases , 
 * taking care of Leap Year days difference in a year, 
 * and date cases month and Year boundary cases (12/31/1980, 01/01/1980 etc)
**/

public static int getAge(Date dateOfBirth) {

    Calendar today = Calendar.getInstance();
    Calendar birthDate = Calendar.getInstance();

    int age = 0;

    birthDate.setTime(dateOfBirth);
    if (birthDate.after(today)) {
        throw new IllegalArgumentException("Can't be born in the future");
    }

    age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);

    // If birth date is greater than todays date (after 2 days adjustment of leap year) then decrement age one year   
    if ( (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3) ||
            (birthDate.get(Calendar.MONTH) > today.get(Calendar.MONTH ))){
        age--;

     // If birth date and todays date are of same month and birth day of month is greater than todays day of month then decrement age
    }else if ((birthDate.get(Calendar.MONTH) == today.get(Calendar.MONTH )) &&
              (birthDate.get(Calendar.DAY_OF_MONTH) > today.get(Calendar.DAY_OF_MONTH ))){
        age--;
    }

    return age;
}

2 votes

Quel est le but du contrôle ? (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3) ? Cela semble inutile avec l'existence des comparaisons du mois et du jour du mois.

13voto

Craigo Points 601

Si vous utilisez GWT, vous serez limité à l'utilisation de java.util.Date, voici une méthode qui prend la date comme des entiers, mais utilise toujours java.util.Date :

public int getAge(int year, int month, int day) {
    Date now = new Date();
    int nowMonth = now.getMonth()+1;
    int nowYear = now.getYear()+1900;
    int result = nowYear - year;

    if (month > nowMonth) {
        result--;
    }
    else if (month == nowMonth) {
        int nowDay = now.getDate();

        if (day > nowDay) {
            result--;
        }
    }
    return result;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X