web-dev-qa-db-fra.com

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

Je souhaite renvoyer un âge en années en tant qu'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 depuis que getYear () est obsolète, je me demande s’il existe un meilleur moyen de le faire? Je ne suis même pas sûr que cela fonctionne correctement, car je n'ai pas (encore) de tests unitaires en place.

128
nojevive

JDK 8 rend cela simple et élégant:

public class AgeCalculator {

    public static int calculateAge(LocalDate birthDate, LocalDate currentDate) {
        if ((birthDate != null) && (currentDate != null)) {
            return Period.between(birthDate, currentDate).getYears();
        } else {
            return 0;
        }
    }
}

Un test JUnit pour démontrer son utilisation: 

public class AgeCalculatorTest {

    @Test
    public void testCalculateAge_Success() {
        // setup
        LocalDate birthDate = LocalDate.of(1961, 5, 17);
        // exercise
        int actual = AgeCalculator.calculateAge(birthDate, LocalDate.of(2016, 7, 12));
        // assert
        Assert.assertEquals(55, actual);
    }
}

Tout le monde devrait utiliser JDK 8 maintenant. Toutes les versions précédentes ont passé la fin de leur vie de support.

135
duffymo

Découvrez Joda , qui simplifie les calculs de date/heure (Joda est également la base du nouvel apis de date/heure standard Java, vous apprendrez donc une API qui sera bientôt standard). 

EDIT: Java 8 a quelque chose de très similaire et vaut le détour.

par exemple. 

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

ce qui est aussi simple que vous pourriez vouloir. Les éléments antérieurs à Java 8 sont (comme vous l'avez indiqué) quelque peu peu intuitifs.

165
Brian Agnew
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
41
cletus

Réponse moderne et aperçu

a) Java-8 (paquet Java.time)

LocalDate start = LocalDate.of(1996, 2, 29);
LocalDate end = LocalDate.of(2014, 2, 28); // use for age-calculation: LocalDate.now()
long years = ChronoUnit.YEARS.between(start, end);
System.out.println(years); // 17

Notez que l'expression LocalDate.now() est implicitement liée au fuseau horaire du système (souvent négligé par les utilisateurs). Par souci de clarté, il est généralement préférable d’utiliser la méthode surchargée now(ZoneId.of("Europe/Paris")) en spécifiant un fuseau horaire explicite (ici, "Europe/Paris" par exemple). Si le fuseau horaire du système est demandé, ma préférence personnelle est d'écrire LocalDate.now(ZoneId.systemDefault()) afin de clarifier la relation avec le fuseau horaire du système. C'est plus un effort d'écriture mais rend la lecture plus facile.

b) Joda-Time

Veuillez noter que la solution Joda-Time proposée et acceptée produit un résultat de calcul différent pour les dates indiquées ci-dessus (cas rare), à ​​savoir:

LocalDate birthdate = new LocalDate(1996, 2, 29);
LocalDate now = new LocalDate(2014, 2, 28); // test, in real world without args
Years age = Years.yearsBetween(birthdate, now);
System.out.println(age.getYears()); // 18

Je considère cela comme un petit bug, mais l'équipe Joda a un point de vue différent sur ce comportement étrange et ne veut pas le réparer (bizarre parce que le jour de mois de la date de fin est plus petit que celui de début un de moins). Voir aussi cette clôture numéro .

c) Java.util.Calendar etc.

Pour comparaison, voir les différentes autres réponses. Je ne recommanderais pas du tout l'utilisation de ces classes obsolètes car le code résultant est toujours sujette aux erreurs dans certains cas exotiques et/ou beaucoup trop complexe compte tenu du fait que la question initiale semble si simple. En 2015, nous avons vraiment de meilleures bibliothèques.

d) à propos de Date4J:

La solution proposée est simple mais échouera parfois en cas d’année bissextile. Juste évaluer le jour de l'année n'est pas fiable.

e) Ma propre bibliothèque Time4J:

Cela fonctionne de manière similaire à Java-8-solution. Il suffit de remplacer LocalDate par PlainDate et ChronoUnit.YEARS par CalendarUnit.YEARS. Cependant, obtenir "aujourd'hui" nécessite une référence explicite à un fuseau horaire.

PlainDate start = PlainDate.of(1996, 2, 29);
PlainDate end = PlainDate.of(2014, 2, 28);
// use for age-calculation (today): 
// => end = SystemClock.inZonalView(EUROPE.PARIS).today();
// or in system timezone: end = SystemClock.inLocalView().today();
long years = CalendarUnit.YEARS.between(start, end);
System.out.println(years); // 17
36
Meno Hochschild
/**
 * 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;
}
17
Farhan Munir

J'utilise simplement les millisecondes dans une année constante à mon avantage:

Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
11
Lou Morda

Si vous utilisez GWT, vous serez limité à l’utilisation de Java.util.Date. Voici une méthode qui prend la date sous forme d’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;
}
10
Craigo

Avec la date4j bibliothèque:

int age = today.getYear() - birthdate.getYear();
if(today.getDayOfYear() < birthdate.getDayOfYear()){
  age = age - 1; 
}
4
John O

La bonne réponse en utilisant JodaTime est:

public int getAge() {
    Years years = Years.yearsBetween(new LocalDate(getBirthDate()), new LocalDate());
    return years.getYears();
}

Vous pouvez même le raccourcir en une seule ligne si vous le souhaitez. J'ai copié l'idée de la réponse de BrianAgnew , mais je crois que c'est plus correct comme vous pouvez le voir dans les commentaires (et cela répond exactement à la question).

4
Fletch

Essayez de copier celui-ci dans votre code, puis utilisez la méthode pour obtenir l'âge.

public static int getAge(Date birthday)
{
    GregorianCalendar today = new GregorianCalendar();
    GregorianCalendar bday = new GregorianCalendar();
    GregorianCalendar bdayThisYear = new GregorianCalendar();

    bday.setTime(birthday);
    bdayThisYear.setTime(birthday);
    bdayThisYear.set(Calendar.YEAR, today.get(Calendar.YEAR));

    int age = today.get(Calendar.YEAR) - bday.get(Calendar.YEAR);

    if(today.getTimeInMillis() < bdayThisYear.getTimeInMillis())
        age--;

    return age;
}
3
Kevin

J'utilise ce morceau de code pour le calcul de l'âge, j'espère que cela aidera ... pas de bibliothèques utilisées

private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

public static int calculateAge(String date) {

    int age = 0;
    try {
        Date date1 = dateFormat.parse(date);
        Calendar now = Calendar.getInstance();
        Calendar dob = Calendar.getInstance();
        dob.setTime(date1);
        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);
        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--;
            }
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return age ;
}
2
Ameen Maheen

Ceci est une version améliorée de celle ci-dessus ... étant donné que vous voulez que l'âge soit un "int". parce que parfois vous ne voulez pas remplir votre programme avec un tas de bibliothèques.

public int getAge(Date dateOfBirth) {
    int age = 0;
    Calendar born = Calendar.getInstance();
    Calendar now = Calendar.getInstance();
    if(dateOfBirth!= null) {
        now.setTime(new Date());
        born.setTime(dateOfBirth);  
        if(born.after(now)) {
            throw new IllegalArgumentException("Can't be born in the future");
        }
        age = now.get(Calendar.YEAR) - born.get(Calendar.YEAR);             
        if(now.get(Calendar.DAY_OF_YEAR) < born.get(Calendar.DAY_OF_YEAR))  {
            age-=1;
        }
    }  
    return age;
}
2
cass_

Il est peut-être surprenant de noter que vous n'avez pas besoin de savoir combien de jours ou de mois il y a dans une année ni combien de jours sont dans ces mois, de même, vous n'avez pas besoin de connaître les années bissextiles, les secondes bissextiles de cette substance en utilisant cette méthode simple, 100% précise:

public static int age(Date birthday, Date date) {
    DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
    int d1 = Integer.parseInt(formatter.format(birthday));
    int d2 = Integer.parseInt(formatter.format(date));
    int age = (d2-d1)/10000;
    return age;
}
2
weston

Les champs naissance et effet sont tous deux des champs de date: 

Calendar bir = Calendar.getInstance();
bir.setTime(birth);
int birthNm = bir.get(Calendar.DAY_OF_YEAR);
int birthYear = bir.get(Calendar.YEAR);
Calendar eff = Calendar.getInstance();
eff.setTime(effect);

Il s’agit essentiellement d’une modification de la solution de John O sans utiliser de méthodes dépréciées. J'ai passé pas mal de temps à essayer d'intégrer son code dans mon code. Peut-être que cela sauvera d'autres personnes ce temps-là.

2
John B
public class CalculateAge { 

private int age;

private void setAge(int age){

    this.age=age;

}
public void calculateAge(Date date){

    Calendar calendar=Calendar.getInstance();

    Calendar calendarnow=Calendar.getInstance();    

    calendarnow.getTimeZone();

    calendar.setTime(date);

    int getmonth= calendar.get(calendar.MONTH);

    int getyears= calendar.get(calendar.YEAR);

    int currentmonth= calendarnow.get(calendarnow.MONTH);

    int currentyear= calendarnow.get(calendarnow.YEAR);

    int age = ((currentyear*12+currentmonth)-(getyears*12+getmonth))/12;

    setAge(age);
}
public int getAge(){

    return this.age;

}
1

Stringdateofbirth a la date de naissance. et le format est ce que vous voulez (défini dans la ligne suivante):

org.joda.time.format.DateTimeFormatter formatter =  org.joda.time.format.DateTimeFormat.forPattern("mm/dd/yyyy");

Voici comment formater:

org.joda.time.DateTime birthdateDate = formatter.parseDateTime(dateofbirth );
org.joda.time.DateMidnight birthdate = new         org.joda.time.DateMidnight(birthdateDate.getYear(), birthdateDate.getMonthOfYear(), birthdateDate.getDayOfMonth() );
org.joda.time.DateTime now = new org.joda.time.DateTime();
org.joda.time.Years age = org.joda.time.Years.yearsBetween(birthdate, now);
Java.lang.String ageStr = Java.lang.String.valueOf (age.getYears());

La variable ageStr aura les années.

1
user1955658

J'apprécie toutes les réponses correctes mais c'est la réponse de Kotlin pour la même question

J'espère que cela serait utile aux développeurs de Kotlin 

fun calculateAge(birthDate: Date): Int {
        val now = Date()
        val timeBetween = now.getTime() - birthDate.getTime();
        val yearsBetween = timeBetween / 3.15576e+10;
        return Math.floor(yearsBetween).toInt()
    }
1
ramana vv

Elégante, apparemment correcte, variante basée sur la différence d’horodatage de la solution de Yaron Ronen.

J'inclus un test unité pour prouver quand et pourquoi ce n'est pas correct. Il est impossible en raison (éventuellement) d'un nombre différent de jours bissextiles (et de secondes) dans toute différence d'horodatage. La différence devrait être max + -1 jour (et une seconde) pour cet algorithme, voir test2 (), alors que la solution de Yaron Ronen basée sur l'hypothèse totalement constante de timeDiff / MILLI_SECONDS_YEAR peut différer de 10 jours pour un utilisateur de 40 ans, néanmoins cette variante est également incorrecte .

C'est délicat, car cette variante améliorée, qui utilise la formule diffAsCalendar.get(Calendar.YEAR) - 1970, renvoie la plupart du temps des résultats corrects, sous la forme du nombre d'années bissextiles identique en moyenne entre deux dates.

/**
 * Compute person's age based on timestamp difference between birth date and given date
 * and prove it is INCORRECT approach.
 */
public class AgeUsingTimestamps {

public int getAge(Date today, Date dateOfBirth) {
    long diffAsLong = today.getTime() - dateOfBirth.getTime();
    Calendar diffAsCalendar = Calendar.getInstance();
    diffAsCalendar.setTimeInMillis(diffAsLong);
    return diffAsCalendar.get(Calendar.YEAR) - 1970; // base time where timestamp=0, precisely 1/1/1970 00:00:00 
}

    final static DateFormat df = new SimpleDateFormat("dd.MM.yyy HH:mm:ss");

    @Test
    public void test1() throws Exception {
        Date dateOfBirth = df.parse("10.1.2000 00:00:00");
        assertEquals(87, getAge(df.parse("08.1.2088 23:59:59"), dateOfBirth));
        assertEquals(87, getAge(df.parse("09.1.2088 23:59:59"), dateOfBirth));
        assertEquals(88, getAge(df.parse("10.1.2088 00:00:01"), dateOfBirth));
    }

    @Test
    public void test2() throws Exception {
        // between 2000 and 2021 was 6 leap days
        // but between 1970 (base time) and 1991 there was only 5 leap days
        // therefore age is switched one day earlier
            // See http://www.onlineconversion.com/leapyear.htm
        Date dateOfBirth = df.parse("10.1.2000 00:00:00");
        assertEquals(20, getAge(df.parse("08.1.2021 23:59:59"), dateOfBirth));
        assertEquals(20, getAge(df.parse("09.1.2021 23:59:59"), dateOfBirth)); // ERROR! returns incorrect age=21 here
        assertEquals(21, getAge(df.parse("10.1.2021 00:00:01"), dateOfBirth));
    }
}
1
Espinosa

Qu'en est-il de celui-ci?

public Integer calculateAge(Date date) {
    if (date == null) {
        return null;
    }
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date);
    Calendar cal2 = Calendar.getInstance();
    int i = 0;
    while (cal1.before(cal2)) {
        cal1.add(Calendar.YEAR, 1);
        i += 1;
    }
    return i;
}
1
Andre P.

Voici le code Java pour calculer l'âge en année, mois et jours. 

public static AgeModel calculateAge(long birthDate) {
    int years = 0;
    int months = 0;
    int days = 0;

    if (birthDate != 0) {
        //create calendar object for birth day
        Calendar birthDay = Calendar.getInstance();
        birthDay.setTimeInMillis(birthDate);

        //create calendar object for current day
        Calendar now = Calendar.getInstance();
        Calendar current = Calendar.getInstance();
        //Get difference between years
        years = now.get(Calendar.YEAR) - birthDay.get(Calendar.YEAR);

        //get months
        int currMonth = now.get(Calendar.MONTH) + 1;
        int birthMonth = birthDay.get(Calendar.MONTH) + 1;

        //Get difference between months
        months = currMonth - birthMonth;

        //if month difference is in negative then reduce years by one and calculate the number of months.
        if (months < 0) {
            years--;
            months = 12 - birthMonth + currMonth;
        } else if (months == 0 && now.get(Calendar.DATE) < birthDay.get(Calendar.DATE)) {
            years--;
            months = 11;
        }

        //Calculate the days
        if (now.get(Calendar.DATE) > birthDay.get(Calendar.DATE))
            days = now.get(Calendar.DATE) - birthDay.get(Calendar.DATE);
        else if (now.get(Calendar.DATE) < birthDay.get(Calendar.DATE)) {
            int today = now.get(Calendar.DAY_OF_MONTH);
            now.add(Calendar.MONTH, -1);
            days = now.getActualMaximum(Calendar.DAY_OF_MONTH) - birthDay.get(Calendar.DAY_OF_MONTH) + today;
        } else {
            days = 0;
            if (months == 12) {
                years++;
                months = 0;
            }
        }
    }

    //Create new Age object
    return new AgeModel(days, months, years);
}
0
akshay

Le moyen le plus simple sans aucune bibliothèque:

    long today = new Date().getTime();
    long diff = today - birth;
    long age = diff / DateUtils.YEAR_IN_MILLIS;
0
lxknvlk
/**
 * Compute from string date in the format of yyyy-MM-dd HH:mm:ss the age of a person.
 * @author Yaron Ronen
 * @date 04/06/2012  
 */
private int computeAge(String sDate)
{
    // Initial variables.
    Date dbDate = null;
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");      

    // Parse sDate.
    try
    {
        dbDate = (Date)dateFormat.parse(sDate);
    }
    catch(ParseException e)
    {
        Log.e("MyApplication","Can not compute age from date:"+sDate,e);
        return ILLEGAL_DATE; // Const = -2
    }

    // Compute age.
    long timeDiff = System.currentTimeMillis() - dbDate.getTime();      
    int age = (int)(timeDiff / MILLI_SECONDS_YEAR);  // MILLI_SECONDS_YEAR = 31558464000L;

    return age; 
}
0
Yaron Ronen

Avec Java 8, nous pouvons calculer l’âge d’une personne avec une ligne de code:

public int calCAge(int year, int month,int days){             
    return LocalDate.now().minus(Period.of(year, month, days)).getYear();         
}
0
Mam's