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 LocalDate
par PlainDate
et ChronoUnit.YEARS
par 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