Comment calculer l'âge d'une personne en Java?

147

Je veux 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 comme 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.

nojevive
la source
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.
cletus
Étant donné qu'il renvoie un int, pouvez-vous clarifier ce que vous entendez par un âge «correct»?
Brian Agnew
2
Date vs Calendar est un concept fondamental qui peut être glané à la lecture de la documentation Java. Je ne peux pas comprendre pourquoi ce serait tellement voté.
demongolem
@demongolem ??? La date et le calendrier sont faciles à comprendre?! Non pas du tout. Il y a des millions de questions sur le sujet ici sur Stack Overflow. Le projet Joda-Time a produit l'une des bibliothèques les plus populaires, pour remplacer ces classes de date-heure gênantes. Plus tard, Sun, Oracle et la communauté JCP ont accepté JSR 310 ( java.time ), admettant que les classes héritées étaient désespérément inadéquates. Pour plus d'informations, consultez le didacticiel d'Oracle .
Basil Bourque

Réponses:

159

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 maintenant utiliser JDK 8. Toutes les versions antérieures ont dépassé la fin de leur durée de vie de support.

duffymo
la source
10
La comparaison DAY_OF_YEAR peut conduire à un résultat erroné lorsqu'il s'agit d'années bissextiles.
sinuhepop
1
La variable dateOfBirth doit être un objet Date. Comment créer un objet Date avec la date de naissance?
Erick
Compte tenu du fait que nous sommes 9 ans plus tard, et au cas où Java 8 serait utilisé, cela devrait être la solution à utiliser.
nojevive
JDK 9 est la version de production actuelle. Plus vrai que jamais.
duffymo
2
@SteveOh Je ne suis pas d'accord. Je préférerais ne pas accepter nullde tout, mais au lieu d' utiliser Objects.requireNonNull.
MC Emperor
170

Découvrez Joda , qui simplifie les calculs de date / heure (Joda est également la base des nouvelles API de date / heure standard de Java, vous apprendrez donc une API 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 le souhaitez. Les éléments pré-Java 8 sont (comme vous l'avez identifiés) quelque peu peu intuitifs.

Brian Agnew
la source
2
@ HoàngLong: D'après les JavaDocs: "Cette classe ne représente pas un jour, mais l'instant milliseconde à minuit. Si vous avez besoin d'une classe qui représente la journée entière, alors un Interval ou un LocalDate peut être plus approprié." Nous avons vraiment ne voulons représenter une date ici.
Jon Skeet
Si vous voulez le faire comme le suggère @JohnSkeet, c'est comme ceci: Ans age = Years.yearsB Between (new LocalDate (getBirthDate ()), new LocalDate ());
Fletch
Je ne sais pas pourquoi j'ai utilisé DateMidnight, et je note maintenant qu'il est obsolète. Maintenant changé pour utiliser LocalDate
Brian Agnew
2
@IgorGanapolsky En effet, la principale différence est: Joda-Time utilise des constructeurs tandis que Java-8 et ThreetenBP utilisent des méthodes de fabrique statique. Pour un bug subtil dans la façon dont Joda-Time calcule l'âge, veuillez regarder ma réponse où j'ai donné un aperçu du comportement des différentes bibliothèques.
Meno Hochschild
43
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
cletus
la source
Ouais, la classe de calendrier est terrible. Malheureusement, au travail, je dois parfois l'utiliser: /. Merci Cletus d'avoir posté ceci
Steve
1
Remplacez Calendar.MONTH et Calendar.DAY_OF_MONTH par Calendar.DAY_OF_YEAR et ce sera au moins un peu plus propre
Tobbbe
@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. DAY_OF_YEAR ne fonctionnera pas.
Airsource Ltd le
42

Réponse moderne et vue d'ensemble

a) Java-8 (package 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 (qui est souvent négligé par les utilisateurs). Pour plus de clarté, il est généralement préférable d'utiliser la méthode surchargée en now(ZoneId.of("Europe/Paris"))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())pour rendre la relation avec le fuseau horaire du système plus claire. C'est plus d'effort d'écriture, mais cela facilite la lecture.

b) Joda-Time

Veuillez noter que la solution Joda-Time proposée et acceptée donne un résultat de calcul différent pour les dates indiquées ci-dessus (un 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 corriger (bizarre parce que le jour du mois de la date de fin est plus petit que la date de début, donc l'année devrait être un de moins). Voir aussi cette fermeture question .

c) java.util.Calendar etc.

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

d) À propos de Date4J:

La solution proposée est simple mais échouera parfois en cas d'années bissextiles. Evaluer simplement le jour de l'année n'est pas fiable.

e) Ma propre bibliothèque Time4J :

Cela fonctionne de la même manière que Java-8-solution. Remplacez simplement LocalDatepar PlainDateet ChronoUnit.YEARSpar CalendarUnit.YEARS. Cependant, obtenir «aujourd'hui» nécessite une référence de fuseau horaire explicite.

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
Meno Hochschild
la source
1
Merci pour la version Java 8! Cela m'a fait gagner du temps :) Il ne me reste plus qu'à trouver comment extraire les mois restants. Par exemple 1 an et 1 mois. :)
thomas77
2
@ thomas77 Merci pour la réponse, les années et les mois combinés (et peut-être les jours) peuvent être effectués en utilisant `java.time.Period 'en Java-8. Si vous souhaitez également prendre en compte d'autres unités comme les heures, Java-8 n'offre pas de solution.
Meno Hochschild
Merci encore (et pour la réponse rapide) :)
thomas77
1
Je suggère de spécifier un fuseau horaire lors de l'utilisation LocalDate.now. Si omis, le fuseau horaire par défaut actuel de la machine virtuelle Java est appliqué implicitement. Cette valeur par défaut peut changer entre les machines / OS / paramètres, et peut également à tout moment pendant l'exécution par n'importe quel appel de code setDefault. Je recommande d'être précis, commeLocalDate.now( ZoneId.for( "America/Montreal" ) )
Basil Bourque
1
@GoCrafter_LP Oui, vous pouvez appliquer ThreetenABP simulant Java-8, ou Joda-Time-Android (de D. Lew) ou ma lib Time4A pour ces anciennes versions d'Android.
Meno Hochschild
17
/**
 * 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;
}
Farhan Munir
la source
2
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 de comparaisons de mois et de jour de mois.
Jed Schaaf
13

J'utilise simplement les millisecondes dans une valeur constante d'un an à mon avantage:

Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
Lou Morda
la source
2
Ce n'est pas une réponse exacte ... l'année n'est pas 3.156e + 10 mais 3.15576e + 10 (quart de jour!)
Maher Abuthraa
1
Cela ne fonctionne pas, certaines années sont des années bissextiles et ont une valeur de ms différente
Greg Ennis
12

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;
}
Craigo
la source
5

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 pense que c'est plus correct comme vous le voyez dans les commentaires (et cela répond exactement à la question).

Fletch
la source
4

Avec la bibliothèque date4j :

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

Ceci est une version améliorée de celle ci-dessus ... considérant 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;
}
cass
la source
4

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 ou combien de jours il y a dans ces mois, de même, vous n'avez pas besoin de connaître les années bissextiles, les secondes intercalaires ou tout autre de ces choses en utilisant cette méthode simple et précise à 100%:

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;
}
Weston
la source
Je cherche une solution pour java 6 et 5. C'est simple mais précis.
Jj Tuibeo
3

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;
}
Kevin
la source
Les réponses au code uniquement sont déconseillées. Il serait préférable d'expliquer pourquoi ce code peut répondre à la question du PO.
рüффп
C'est une évidence en fait .. mais mettra à jour juste pour répondre à votre préoccupation
Kevin
3

J'utilise ce morceau de code pour le calcul de l'âge, j'espère que cela aide .. aucune bibliothèque utilisée

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 ;
}
Ameen Maheen
la source
2

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 de faire fonctionner son code dans mon code. Peut-être que cela en sauvera d'autres cette fois.

Jean B
la source
2
pouvez-vous expliquer cela un peu mieux? comment cela calcule-t-il l'âge?
Jonathan S. Fisher
1

Et celui-là?

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;
}
André P.
la source
C'est une suggestion vraiment mignonne (lorsque vous n'utilisez pas Joda et que vous ne pouvez pas utiliser Java 8), mais l'algorithme est légèrement faux car vous êtes à 0 jusqu'à ce que toute la première année passe. Vous devez donc ajouter une année à la date avant de démarrer la boucle while.
Dagmar
1

String dateofbirtha la date de naissance. et le format est n'importe quel (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 ageStraura les années.

user1955658
la source
1

Variante élégante, apparemment correcte , basée sur la différence d'horodatage de la solution Yaron Ronen.

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

C'est délicat, car cette variante améliorée, utilisant une formule diffAsCalendar.get(Calendar.YEAR) - 1970, renvoie des résultats corrects la plupart du temps, car le nombre d'années bissextiles est en moyenne le même 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));
    }
}
Espinosa
la source
1
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;

}
Vahid Pooreftekhari
la source
0
/**
 * 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; 
}
Yaron Ronen
la source
Je ne sais pas si vous avez vraiment testé celui-ci ou non, mais pour d'autres, cette méthode a un défaut. si aujourd'hui est le même mois que votre date de naissance et aujourd'hui <anniversaire, il indique toujours l'âge réel + 1, c'est-à-dire, par exemple, si votre anniversaire est le 7 septembre 1986, et aujourd'hui est le 1er septembre 2013, il vous montrera 27 à la place du 26.
srahul07
2
Cela ne peut pas être vrai car le nombre de millisecondes dans une année n'est PAS CONSTANT. Les années bissextiles ont un jour de plus, c'est-à-dire beaucoup plus de millisecondes que les autres. Pour une personne de 40 ans, votre algorithme peut signaler son anniversaire 9 à 10 jours plus tôt que ce n'est vraiment le cas! Il y a aussi des secondes intercalaires.
Espinosa
0

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);
}
akshay
la source
0

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;
lxknvlk
la source
1
Ce code utilise d'anciennes classes date-heure gênantes qui sont désormais héritées, supplantées par les classes java.time. Utilisez plutôt les classes modernes construites en Java: ChronoUnit.YEARS.between( LocalDate.of( 1968 , Month.MARCH , 23 ) , LocalDate.now() ). Voir la bonne réponse
Basil Bourque
DateUtilsest une bibliothèque
Terran
0

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();         
}
Mam's
la source
âge en année ou en mois? Et bébé en mois?
gumuruh
-1
public int getAge(Date dateOfBirth) 
{
    Calendar now = Calendar.getInstance();
    Calendar dob = Calendar.getInstance();

    dob.setTime(dateOfBirth);

    if (dob.after(now)) 
    {
        throw new IllegalArgumentException("Can't be born in the future");
    }

    int age = now.get(Calendar.YEAR) - dob.get(Calendar.YEAR);

    if (now.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)) 
    {
        age--;
    }

    return age;
}
Stradivariuz
la source
comme @sinuhepop l'a remarqué "La comparaison DAY_OF_YEAR peut conduire à un résultat erroné lorsqu'il s'agit d'années bissextiles"
Krzysztof Kot
-1
import java.io.*;

class AgeCalculator
{
    public static void main(String args[])
    {
        InputStreamReader ins=new InputStreamReader(System.in);
        BufferedReader hey=new BufferedReader(ins);

        try
        {
            System.out.println("Please enter your name: ");
            String name=hey.readLine();

            System.out.println("Please enter your birth date: ");
            String date=hey.readLine();

            System.out.println("please enter your birth month:");
            String month=hey.readLine();

            System.out.println("please enter your birth year:");
            String year=hey.readLine();

            System.out.println("please enter current year:");
            String cYear=hey.readLine();

            int bDate = Integer.parseInt(date);
            int bMonth = Integer.parseInt(month);
            int bYear = Integer.parseInt(year);
            int ccYear=Integer.parseInt(cYear);

            int age;

            age = ccYear-bYear;
            int totalMonth=12;
            int yourMonth=totalMonth-bMonth;

            System.out.println(" Hi " + name + " your are " + age + " years " + yourMonth + " months old ");
        }
        catch(IOException err)
        {
            System.out.println("");
        }
    }
}
Surendar S
la source
-1
public int getAge(String birthdate, String today){
    // birthdate = "1986-02-22"
    // today = "2014-09-16"

    // String class has a split method for splitting a string
    // split(<delimiter>)
    // birth[0] = 1986 as string
    // birth[1] = 02 as string
    // birth[2] = 22 as string
    // now[0] = 2014 as string
    // now[1] = 09 as string
    // now[2] = 16 as string
    // **birth** and **now** arrays are automatically contains 3 elements 
    // split method here returns 3 elements because of yyyy-MM-dd value
    String birth[] = birthdate.split("-");
    String now[] = today.split("-");
    int age = 0;

    // let us convert string values into integer values
    // with the use of Integer.parseInt(<string>)
    int ybirth = Integer.parseInt(birth[0]);
    int mbirth = Integer.parseInt(birth[1]);
    int dbirth = Integer.parseInt(birth[2]);

    int ynow = Integer.parseInt(now[0]);
    int mnow = Integer.parseInt(now[1]);
    int dnow = Integer.parseInt(now[2]);

    if(ybirth < ynow){ // has age if birth year is lesser than current year
        age = ynow - ybirth; // let us get the interval of birth year and current year
        if(mbirth == mnow){ // when birth month comes, it's ok to have age = ynow - ybirth if
            if(dbirth > dnow) // birth day is coming. need to subtract 1 from age. not yet a bday
                age--;
        }else if(mbirth > mnow){ age--; } // birth month is comming. need to subtract 1 from age            
    }

    return age;
}
Jhonie
la source
Remarque: le format de la date est: aaaa-MM-jj. Ceci est un code générique qui est testé en jdk7 ...
Jhonie
1
Il serait utile de fournir des commentaires ou d'expliquer comment utiliser exactement ce code. Le simple vidage de code est généralement déconseillé, et le demandeur peut ne pas comprendre vos choix derrière pourquoi vous avez décidé de coder votre méthode de cette façon.
rayryeng
@rayryeng: Jhonie a déjà ajouté des commentaires dans le code. Cela suffit pour comprendre. Veuillez réfléchir et lire avant de donner un tel commentaire.
akshay
@Akshay ce n'était pas évident pour moi. Avec le recul, il semblait que le code avait été vidé. Je ne lis généralement pas les commentaires. Ce serait bien si ceux-ci étaient retirés du corps et placés séparément comme explication. C'est ma préférence cependant et nous pouvons être d'accord pour ne pas être d'accord ici ... Cela étant dit, j'ai même oublié d'avoir écrit ce commentaire car il y a presque deux ans.
rayryeng
@rayryeng: La raison de ce commentaire était que l'écriture de commentaires négatifs décourageait les gens d'utiliser un si beau forum. Nous devons donc les encourager en leur faisant des commentaires positifs. Bdw, pas d'offense. À votre santé!!!
akshay
-1
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.Period;

public class AgeCalculator1 {

    public static void main(String args[]) {
        LocalDate start = LocalDate.of(1970, 2, 23);
        LocalDate end = LocalDate.now(ZoneId.systemDefault());

        Period p = Period.between(start, end);
        //The output of the program is :
        //45 years 6 months and 6 days.
        System.out.print(p.getYears() + " year" + (p.getYears() > 1 ? "s " : " ") );
        System.out.print(p.getMonths() + " month" + (p.getMonths() > 1 ? "s and " : " and ") );
        System.out.print(p.getDays() + " day" + (p.getDays() > 1 ? "s.\n" : ".\n") );
    }//method main ends here.
}
Dilshad Rana
la source
3
Merci d'avoir participé à StackOverflow. Quelques suggestions pour vous. [A] Veuillez inclure une discussion avec votre réponse. StackOverflow.com est censé être bien plus qu'une simple collection d'extraits de code. Par exemple, notez comment votre code utilise le nouveau framework java.time alors que la plupart des autres réponses utilisent java.util.Date et Joda-Time. [B] Veuillez comparer votre réponse avec la réponse similaire de Meno Hochschild qui utilise également java.time. Expliquez comment le vôtre est meilleur ou abordez le problème sous un angle différent. Ou rétractez le vôtre sinon mieux.
Basil Bourque
-1
public int getAge(Date birthDate) {
    Calendar a = Calendar.getInstance(Locale.US);
    a.setTime(date);
    Calendar b = Calendar.getInstance(Locale.US);
    int age = b.get(YEAR) - a.get(YEAR);
    if (a.get(MONTH) > b.get(MONTH) || (a.get(MONTH) == b.get(MONTH) && a.get(DATE) > b.get(DATE))) {
        age--;
    }
    return age;
}
sinuhepop
la source
-1

J'apprécie toutes les réponses correctes mais c'est la réponse 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()
    }
ramana vv
la source
Cela semble plutôt idiot de faire de tels calculs alors que nous avons à notre disposition les classes java.time leaders de l'industrie .
Basil Bourque
Requêtes OP en Java.
Terran