Je souhaite 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 depuis que 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.
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 utiliser JDK 8 maintenant. Toutes les versions précédentes ont passé la fin de leur vie de support.
Découvrez Joda , qui simplifie les calculs de date/heure (Joda est également la base du nouvel apis de date/heure standard Java, vous apprendrez donc une API qui sera 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 pourriez vouloir. Les éléments antérieurs à Java 8 sont (comme vous l'avez indiqué) quelque peu peu intuitifs.
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
a) Java-8 (paquet 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 (souvent négligé par les utilisateurs). Par souci de clarté, il est généralement préférable d’utiliser la méthode surchargée now(ZoneId.of("Europe/Paris"))
en 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())
afin de clarifier la relation avec le fuseau horaire du système. C'est plus un effort d'écriture mais rend la lecture plus facile.
b) Joda-Time
Veuillez noter que la solution Joda-Time proposée et acceptée produit un résultat de calcul différent pour les dates indiquées ci-dessus (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 réparer (bizarre parce que le jour de mois de la date de fin est plus petit que celui de début un de moins). Voir aussi cette clôture numéro .
c) Java.util.Calendar etc.
Pour comparaison, voir les différentes autres réponses. Je ne recommanderais pas du tout l'utilisation de ces classes obsolètes car le code résultant est toujours sujette aux erreurs dans certains cas exotiques et/ou beaucoup trop complexe compte tenu du fait que la question initiale semble si simple. En 2015, nous avons vraiment de meilleures bibliothèques.
d) à propos de Date4J:
La solution proposée est simple mais échouera parfois en cas d’année bissextile. Juste évaluer le jour de l'année n'est pas fiable.
e) Ma propre bibliothèque Time4J:
Cela fonctionne de manière similaire à Java-8-solution. Il suffit de remplacer LocalDate
par PlainDate
et ChronoUnit.YEARS
par CalendarUnit.YEARS
. Cependant, obtenir "aujourd'hui" nécessite une référence explicite à un fuseau horaire.
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;
}
J'utilise simplement les millisecondes dans une année constante à mon avantage:
Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
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;
}
Avec la date4j bibliothèque:
int age = today.getYear() - birthdate.getYear();
if(today.getDayOfYear() < birthdate.getDayOfYear()){
age = age - 1;
}
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 crois que c'est plus correct comme vous pouvez le voir dans les commentaires (et cela répond exactement à la question).
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;
}
J'utilise ce morceau de code pour le calcul de l'âge, j'espère que cela aidera ... pas de bibliothèques utilisées
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 ;
}
Ceci est une version améliorée de celle ci-dessus ... étant donné 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;
}
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 ni combien de jours sont dans ces mois, de même, vous n'avez pas besoin de connaître les années bissextiles, les secondes bissextiles de cette substance en utilisant cette méthode simple, 100% précise:
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;
}
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 d'intégrer son code dans mon code. Peut-être que cela sauvera d'autres personnes ce temps-là.
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;
}
String
dateofbirth
a la date de naissance. et le format est ce que vous voulez (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 ageStr
aura les années.
J'apprécie toutes les réponses correctes mais c'est la réponse de 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()
}
Elégante, apparemment correcte, variante basée sur la différence d’horodatage de la solution de Yaron Ronen.
J'inclus un test unité pour prouver quand et pourquoi ce n'est pas correct. Il est impossible en raison (éventuellement) d'un nombre différent de jours bissextiles (et de secondes) dans toute différence d'horodatage. La différence devrait être max + -1 jour (et une seconde) pour cet algorithme, voir test2 (), alors que la solution de Yaron Ronen basée sur l'hypothèse totalement constante de timeDiff / MILLI_SECONDS_YEAR
peut différer de 10 jours pour un utilisateur de 40 ans, néanmoins cette variante est également incorrecte .
C'est délicat, car cette variante améliorée, qui utilise la formule diffAsCalendar.get(Calendar.YEAR) - 1970
, renvoie la plupart du temps des résultats corrects, sous la forme du nombre d'années bissextiles identique en moyenne 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));
}
}
Qu'en est-il de celui-ci?
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;
}
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);
}
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;
/**
* 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;
}
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();
}