¿Cómo calculo la edad de alguien en Java?

Quiero devolver una edad en años como int en un método Java. Lo que tengo ahora es lo siguiente donde getBirthDate () devuelve un objeto Date (con la fecha de nacimiento ;-)):

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

Pero como getYear () está en desuso, me pregunto si existe una mejor manera de hacerlo. Ni siquiera estoy seguro de que esto funcione correctamente, ya que no tengo pruebas de unidades en su lugar (todavía).

JDK 8 lo hace fácil y elegante:

 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; } } } 

Una prueba JUnit para demostrar su uso:

 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); } } 

Todos deberían estar usando JDK 8 por ahora. Todas las versiones anteriores han pasado al final de su vida de soporte.

Eche un vistazo a Joda , que simplifica los cálculos de fecha / hora (Joda también es la base de las nuevas apis estándar de fecha / hora de Java, por lo que aprenderá una API que pronto será estándar).

EDITAR: Java 8 tiene algo muy similar y vale la pena echarle un vistazo.

p.ej

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

que es tan simple como podrías desear Las cosas previas a Java 8 son (como has identificado) algo poco intuitivas.

 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 

Respuesta moderna y visión general

a) Java-8 (java.time-package)

 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 

Tenga en cuenta que la expresión LocalDate.now() está implícitamente relacionada con la zona horaria del sistema (que los usuarios a menudo pasan por alto). Para mayor claridad, generalmente es mejor usar el método sobrecargado now(ZoneId.of("Europe/Paris")) especificando una zona horaria explícita (aquí “Europa / París” como ejemplo). Si se solicita la zona horaria del sistema, mi preferencia personal es escribir LocalDate.now(ZoneId.systemDefault()) para LocalDate.now(ZoneId.systemDefault()) la relación con la zona horaria del sistema. Esto es más esfuerzo de escritura pero facilita la lectura.

b) Joda-Time

Tenga en cuenta que la solución Joda-Time propuesta y aceptada arroja un resultado de cálculo diferente para las fechas que se muestran arriba (un caso raro), a saber:

 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 

Considero esto como un pequeño error, pero el equipo de Joda tiene una visión diferente sobre este comportamiento extraño y no quiere arreglarlo (extraño porque el día del mes de la fecha de finalización es menor que la fecha de inicio, por lo que el año debería ser uno menos). Ver también este problema cerrado.

c) java.util.Calendar, etc.

Para comparar, vea las otras varias respuestas. No recomendaría usar estas clases desactualizadas en absoluto porque el código resultante sigue siendo un error en algunos casos exóticos y / o demasiado complejo, considerando el hecho de que la pregunta original suena tan simple. En el año 2015 tenemos bibliotecas realmente mejores.

d) Acerca de Date4J:

La solución propuesta es simple, pero a veces fallará en caso de años bisiestos. Solo evaluar el día del año no es confiable.

e) Mi propia biblioteca Time4J :

Esto funciona de manera similar a la solución Java-8. Simplemente reemplace LocalDate por PlainDate y ChronoUnit.YEARS por CalendarUnit.YEARS . Sin embargo, obtener “hoy” requiere una referencia explícita de zona horaria.

 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 
 /** * 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; } 

Si está usando GWT, se limitará a usar java.util.Date, aquí hay un método que toma la fecha como enteros, pero aún usa 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; } 

Simplemente utilizo los milisegundos en un valor constante de un año para mi ventaja:

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

Con la biblioteca date4j :

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

La respuesta correcta usando JodaTime es:

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

Incluso podrías acortarlo en una línea si quieres. Copié la idea de la respuesta de BrianAgnew , pero creo que esto es más correcto, como puede ver en los comentarios allí (y responde exactamente la pregunta).

Intenta copiar este en tu código, luego usa el método para obtener la edad.

 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; } 

Los campos nacimiento y efecto son ambos campos de fecha:

 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); 

Esto básicamente es una modificación de la solución de John O sin usar métodos depreciados. Pasé bastante tiempo intentando que su código funcionara en mi código. Quizás esto salvará a otros esa vez.

Esta es una versión mejorada de la anterior … teniendo en cuenta que desea que la edad sea un ‘int’. porque a veces no quiere llenar su progtwig con un montón de bibliotecas.

 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; } 

Utilizo este fragmento de código para calcular la edad, espero que esto ayude … no se usen bibliotecas

 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 ; } 

¿Qué hay de este?

 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; } 

String dateofbirth tiene la fecha de nacimiento. y el formato es lo que sea (definido en la siguiente línea):

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

Aquí es cómo formatear:

 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 tendrá los años.

Variante elegante, aparentemente correcta , basada en la diferencia de fecha y hora de la solución de Yaron Ronen.

Incluyo una prueba unitaria para probar cuándo y por qué no es correcta . Es imposible (posiblemente) diferente cantidad de días bisiestos (y segundos) en cualquier diferencia de marca de tiempo. La discrepancia debe ser max + -1 día (y un segundo) para este algoritmo, ver test2 (), mientras que la solución de Yaron Ronen basada en la suposición completamente constante de timeDiff / MILLI_SECONDS_YEAR puede diferir 10 días para un 40 años, sin embargo esta variante es incorrecto también

Es complicado, porque esta variante mejorada, que utiliza la fórmula diffAsCalendar.get(Calendar.YEAR) - 1970 , arroja los resultados correctos la mayor parte del tiempo, como el número de años bisiestos en promedio el mismo entre dos fechas.

 /** * 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)); } } 
 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; } 

Tal vez sea sorprendente notar que no necesita saber cuántos días o meses hay en un año o cuántos días hay en esos meses; asimismo, no necesita saber acerca de los años bisiestos, los segundos intercalares o cualquier otro de esas cosas usando este método sencillo y 100% preciso:

 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; } 

Agradezco todas las respuestas correctas, pero esta es la respuesta kotlin para la misma pregunta

Espero que sea útil para los desarrolladores 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() } 
 /** * 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; } 

Aquí está el código de Java para calcular la edad en años, meses y días.

 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); } 

La forma más sencilla sin ninguna biblioteca:

  long today = new Date().getTime(); long diff = today - birth; long age = diff / DateUtils.YEAR_IN_MILLIS; 

Con Java 8, podemos calcular la edad de una persona con una línea de código:

 public int calCAge(int year, int month,int days){ return LocalDate.now().minus(Period.of(year, month, days)).getYear(); } 
 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; } 
 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(""); } } } 
 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() // 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() 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; } 
 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; } 
 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. }