Respuesta moderna y resumen
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 a menudo los usuarios pasan por alto). Para mayor claridad, generalmente es mejor usar el método sobrecargado que now(ZoneId.of("Europe/Paris"))
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 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 produce un resultado de cálculo diferente para las fechas mostradas anteriormente (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 opinión diferente sobre este comportamiento extraño 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). Ver también este tema cerrado .
c) java.util.Calendar etc.
Para comparar, vea las otras respuestas. No recomendaría usar estas clases desactualizadas porque el código resultante todavía es propenso a errores en algunos casos exóticos y / o es 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. 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