Como calculo a idade de alguém em Java?

Eu quero retornar uma idade em anos como um int em um método Java. O que eu tenho agora é o seguinte, onde getBirthDate () retorna um object Date (com a data de nascimento ;-)):

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

Mas desde que getYear () está obsoleto, eu estou querendo saber se existe uma maneira melhor de fazer isso? Eu nem tenho certeza se isso funciona corretamente, já que não tenho testes de unidade (ainda).

O JDK 8 torna isso fácil e 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; } } } 

Um teste JUnit para demonstrar seu 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 devem estar usando o JDK 8 até agora. Todas as versões anteriores passaram o final de suas vidas de suporte.

Confira o Joda , que simplifica os cálculos de data / hora (o Joda também é a base do novo padrão de data / hora do Java apis, então você estará aprendendo uma API que logo será padrão).

EDIT: Java 8 tem algo muito semelhante e vale a pena conferir.

por exemplo

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

que é tão simples quanto você poderia querer. O material pré-Java 8 é (como você identificou) um tanto não intuitivo.

 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 

Resposta moderna e visão geral

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 

Observe que a expressão LocalDate.now() está implicitamente relacionada ao fuso horário do sistema (que é frequentemente ignorado pelos usuários). Para maior clareza, geralmente é melhor usar o método sobrecarregado now(ZoneId.of("Europe/Paris")) especificando um fuso horário explícito (aqui “Europa / Paris” como exemplo). Se o fuso horário do sistema for solicitado, minha preferência pessoal é escrever LocalDate.now(ZoneId.systemDefault()) para tornar a relação com o fuso horário do sistema mais clara. Isso é mais esforço de escrita, mas facilita a leitura.

b) Joda-Time

Observe que a solução Joda-Time proposta e aceita produz um resultado de cálculo diferente para as datas mostradas acima (um 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 

Eu considero isso como um pequeno bug, mas o Joda-team tem uma visão diferente sobre esse comportamento estranho e não quer consertá-lo (estranho porque o dia do mês da data final é menor do que a data inicial, então o ano deveria ser um a menos). Veja também este assunto fechado.

c) java.util.Calendar etc.

Para comparação, veja as várias outras respostas. Eu não recomendaria o uso dessas classs desatualizadas, pois o código resultante ainda é propenso a erros em alguns casos exóticos e / ou muito complexo, considerando o fato de que a pergunta original parece tão simples. No ano de 2015, temos bibliotecas realmente melhores.

d) Sobre o Date4J:

A solução proposta é simples, mas às vezes falha no caso de anos bissextos. Apenas avaliar o dia do ano não é confiável.

e) Minha própria biblioteca Time4J :

Isso funciona de maneira semelhante à solução Java-8. Basta replace LocalDate por PlainDate e ChronoUnit.YEARS por CalendarUnit.YEARS . No entanto, obter “hoje” requer uma referência explícita de fuso horário.

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

Se você estiver usando o GWT, você estará limitado a usar java.util.Date, aqui está um método que usa a data como inteiros, mas ainda 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; } 

Eu simplesmente uso os milissegundos em um valor constante de ano a meu favor:

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

Com a biblioteca date4j :

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

A resposta correta usando o JodaTime é:

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

Você pode até encurtá-lo em uma linha, se quiser. Copiei a ideia da resposta do BrianAgnew , mas acredito que isso seja mais correto como você vê nos comentários (e responde exatamente à pergunta).

Tente copiar este em seu código e use o método para obter a idade.

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

Os campos nascimento e efeito são ambos campos de data:

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

Isso basicamente é uma modificação da solução de John O sem usar methods depreciados. Passei um bom tempo tentando fazer com que o código dele funcionasse no meu código. Talvez isso salve outros nessa hora.

Esta é uma versão melhorada da acima … considerando que você quer que a idade seja um ‘int’. porque às vezes você não quer encher seu programa com um monte 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; } 

Eu uso este pedaço de código para cálculo de idade, Espero que isso ajude ..no bibliotecas usadas

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

Que tal 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 tem a data de nascimento. e o formato é o que for (definido na seguinte linha):

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

Aqui está como formatar:

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

Variável ageStr terá os anos.

Variante elegante, aparentemente correta , baseada na diferença de data e hora da solução Yaron Ronen.

Estou incluindo um teste de unidade para provar quando e porque não está correto . É impossível devido (possivelmente) a um número diferente de dias bissextos (e segundos) em qualquer diferença de registro de data e hora. A discrepância deve ser no máximo + 1 dia (e um segundo) para este algoritmo, veja test2 (), enquanto que a solução Yaron Ronen baseada na suposição completamente constante de timeDiff / MILLI_SECONDS_YEAR pode diferir 10 dias para um ano 40, entretanto esta variante é incorreto também.

É complicado, porque esta variante melhorada, usando a fórmula diffAsCalendar.get(Calendar.YEAR) - 1970 , retorna resultados corretos na maior parte do tempo, como o número de anos bissextos em média iguais entre duas datas.

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

Talvez seja surpreendente notar que você não precisa saber quantos dias ou meses há em um ano ou quantos dias são nesses meses, da mesma forma, você não precisa saber sobre anos bissextos, segundos bissextos ou qualquer outro. dessas coisas usando este método simples e 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; } 

Eu aprecio todas as respostas corretas, mas esta é a resposta kotlin para a mesma pergunta

Espero que seria útil para desenvolvedores 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; } 

Aqui está o código java para calcular a idade no ano, mês e dias.

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

Maneira mais fácil sem nenhuma biblioteca:

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

Com o Java 8, podemos calcular a idade de uma pessoa com uma linha 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. }