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

Resuelto nojevive asked hace 15 años • 28 respuestas

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 Fecha (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 hay una mejor manera de hacer esto. Ni siquiera estoy seguro de que esto funcione correctamente, ya que no tengo pruebas unitarias implementadas (todavía).

nojevive avatar Jul 12 '09 21:07 nojevive
Aceptado

JDK 8 hace que esto sea 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);
    }
}

Todo el mundo debería estar usando JDK 8 a estas alturas. Todas las versiones anteriores han superado el final de su vida útil.

duffymo avatar Jul 12 '2009 14:07 duffymo

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

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. El material anterior a Java 8 es (como habrás identificado) algo poco intuitivo.

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

EDITAR: Esta respuesta es anterior a las clases de fecha/hora de Java 8 y ya no está actualizada.

Brian Agnew avatar Jul 12 '2009 15:07 Brian Agnew

Respuesta moderna y descripción general.

a) Java-8 (paquete 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

Tenga en cuenta que la expresión LocalDate.now()está implícitamente relacionada con la zona horaria del sistema (que los usuarios suelen pasar por alto). Para mayor claridad, generalmente es mejor utilizar el método sobrecargado now(ZoneId.of("Europe/Paris"))que especifica 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 aclarar la relación con la zona horaria del sistema. Esto supone un mayor esfuerzo de escritura pero facilita la lectura.

b) Tiempo Joda

Tenga en cuenta que la solución Joda-Time propuesta y aceptada produce un resultado de cálculo diferente para las fechas que se muestran arriba (un caso poco común), 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 extraño comportamiento y no quiere solucionarlo (extraño porque el día del mes de la fecha de finalización es menor que el de la fecha de inicio, por lo que el año debería ser uno menos). Véase también este número cerrado .

c) java.util.Calendar, etc.

Para comparar, consulte las otras respuestas. No recomendaría en absoluto el uso de estas clases obsoletas porque el código resultante sigue siendo propenso a errores en algunos casos exóticos y/o demasiado complejo considerando el hecho de que la pregunta original suena muy 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. Simplemente 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 LocalDatepoco PlainDatea ChronoUnit.YEARSpoco CalendarUnit.YEARS. Sin embargo, para obtener "hoy" se requiere una referencia explícita a la 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
Meno Hochschild avatar Jan 02 '2015 07:01 Meno Hochschild
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 avatar Jul 12 '2009 14:07 cletus
/**
 * 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 avatar Sep 21 '2011 07:09 Farhan Munir