Jak obliczyć czyjś wiek w Javie?


147

Chcę zwrócić wiek w latach jako int w metodzie Java. To, co mam teraz, jest następujące, w którym getBirthDate () zwraca obiekt Date (z datą urodzenia ;-)):

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

    Date age = new Date(ageInMillis);

    return age.getYear();
}

Ale ponieważ getYear () jest przestarzałe, zastanawiam się, czy istnieje lepszy sposób na zrobienie tego? Nie jestem nawet pewien, czy to działa poprawnie, ponieważ nie mam (jeszcze) testów jednostkowych.


Zmieniłem zdanie w tej sprawie: drugie pytanie dotyczy tylko przybliżonych lat między datami, a nie naprawdę prawidłowego wieku.
cletus

Biorąc pod uwagę, że zwraca int, czy możesz wyjaśnić, co masz na myśli mówiąc o „prawidłowym” wieku?
Brian Agnew

2
Data vs kalendarz to podstawowa koncepcja, którą można uzyskać z dokumentacji Java. Nie rozumiem, dlaczego tak bardzo za tym głosowano.
demongolem

@demongolem ??? Data i kalendarz są łatwe do zrozumienia ?! Nie, wcale. W witrynie Stack Overflow jest mnóstwo pytań na ten temat. Projekt Joda-Time stworzył jedną z najpopularniejszych bibliotek, aby zastąpić te kłopotliwe klasy data-czas. Później Sun, Oracle i społeczność JCP zaakceptowały JSR 310 ( java.time ), przyznając, że starsze klasy były beznadziejnie nieodpowiednie. Aby uzyskać więcej informacji, zobacz samouczek firmy Oracle .
Basil Bourque

Odpowiedzi:


159

JDK 8 sprawia, że ​​jest to łatwe i eleganckie:

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

Test JUnit w celu wykazania jego zastosowania:

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

Wszyscy powinni już używać JDK 8. Wszystkie wcześniejsze wersje już minęły.


10
Porównanie DAY_OF_YEAR może prowadzić do błędnych wyników w przypadku lat przestępnych.
sinuhepop

1
Zmienna dateOfBirth musi być obiektem Date. Jak mogę utworzyć obiekt Date z datą urodzenia?
Erick

Biorąc pod uwagę fakt, że mamy już 9 lat i w przypadku korzystania z Java 8 powinno to być rozwiązanie, które należy zastosować.
nojevive

JDK 9 to aktualna wersja produkcyjna. Bardziej prawdziwe niż kiedykolwiek.
duffymo

2
@SteveOh Nie zgadzam się. Wolałbym raczej nie akceptować nulls, ale zamiast tego użyć Objects.requireNonNull.
MC Emperor

170

Sprawdź Joda , który upraszcza obliczenia daty / czasu (Joda jest również podstawą nowego standardowego interfejsu API daty / czasu w Javie, więc nauczysz się wkrótce standardowego API).

EDYCJA: Java 8 ma coś bardzo podobnego i warto to sprawdzić.

na przykład

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

co jest tak proste, jak tylko chcesz. Rzeczy sprzed wersji Java 8 są (jak zidentyfikowałeś) nieco nieintuicyjne.


2
@ HoàngLong: Z JavaDocs: „Ta klasa nie reprezentuje dnia, ale milisekundową chwilę o północy. Jeśli potrzebujesz klasy, która reprezentuje cały dzień, bardziej odpowiednie mogą być Interval lub LocalDate.” Naprawdę nie chce reprezentować datę tutaj.
Jon Skeet

Jeśli chcesz to zrobić w sposób sugerowany przez @JohnSkeet, wygląda to tak: Years age = Years.yearsBetween (new LocalDate (getBirthDate ()), new LocalDate ());
Fletch

Nie wiem, dlaczego użyłem DateMidnight, i zauważam, że teraz jest przestarzały. Teraz zmieniono na LocalDate
Brian Agnew


2
@IgorGanapolsky Rzeczywiście główna różnica jest taka: Joda-Time używa konstruktorów, podczas gdy Java-8 i ThreetenBP używają statycznych metod fabrycznych. Jeśli chodzi o subtelny błąd w sposobie obliczania wieku przez Joda-Time, spójrz na moją odpowiedź, w której przedstawiłem przegląd zachowania różnych bibliotek.
Meno Hochschild,

43
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

Tak, zajęcia z kalendarza są okropne. Niestety w pracy czasami muszę go używać: /. Dzięki Cletusowi za opublikowanie tego
Steve

1
Zamień Calendar.MONTH i Calendar.DAY_OF_MONTH na Calendar.DAY_OF_YEAR i będzie przynajmniej trochę czystszy
Tobbbe

@Tobbbe Jeśli urodziłeś się 1 marca w roku przestępnym, twoje urodziny przypadają na 1 marca następnego roku, a nie 2. DAY_OF_YEAR nie będzie działać.
Airsource Ltd

42

Nowoczesna odpowiedź i przegląd

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

Zwróć uwagę, że wyrażenie LocalDate.now()jest niejawnie powiązane ze strefą czasową systemu (która jest często pomijana przez użytkowników). Dla jasności ogólnie lepiej jest użyć przeciążonej metody, now(ZoneId.of("Europe/Paris"))podając wyraźną strefę czasową (tutaj jako przykład „Europa / Paryż”). Jeśli żądana jest strefa czasowa systemu, to ja wolę pisaćLocalDate.now(ZoneId.systemDefault()) aby powiązanie ze strefą czasową systemu było jaśniejsze. To wymaga większego wysiłku przy pisaniu, ale ułatwia czytanie.

b) Czas Joda

Należy pamiętać, że zaproponowane i zaakceptowane rozwiązanie Joda-Time daje inny wynik obliczeń dla dat pokazanych powyżej (rzadki przypadek), a mianowicie:

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

Uważam to za mały błąd, ale zespół Jody ma inny pogląd na to dziwne zachowanie i nie chce go naprawiać (dziwne, ponieważ data zakończenia miesiąca jest mniejsza niż data rozpoczęcia, więc rok powinien być jeden mniej). Zobacz także to zamknięte wydanie .

c) java.util.Calendar itp.

Dla porównania zobacz różne inne odpowiedzi. W ogóle nie polecałbym używania tych przestarzałych klas, ponieważ wynikowy kod jest nadal podatny na błędy w niektórych egzotycznych przypadkach i / lub zbyt skomplikowany, biorąc pod uwagę fakt, że pierwotne pytanie brzmi tak prosto. W 2015 roku mamy naprawdę lepsze biblioteki.

d) o Date4J:

Proponowane rozwiązanie jest proste, ale czasami zawiedzie w przypadku lat przestępnych. Samo oszacowanie dnia roku nie jest wiarygodne.

e) Moja własna biblioteka Time4J :

Działa to podobnie do rozwiązania Java-8. Po prostu wymień LocalDatena PlainDatei ChronoUnit.YEARSdo CalendarUnit.YEARS. Jednak uzyskanie informacji „dzisiaj” wymaga wyraźnego odniesienia do strefy czasowej.

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

1
Dziękujemy za wersję Java 8! Zaoszczędziło mi to trochę czasu :) Teraz muszę tylko wymyślić, jak wydobyć pozostałe miesiące. Np. 1 rok i 1 miesiąc. :)
thomas77

2
@ thomas77 Dziękuję za odpowiedź, łącznie lata i miesiące (a może i dni) można zrobić używając `java.time.Period 'w Javie-8. Jeśli chcesz również wziąć pod uwagę inne jednostki, takie jak godziny, Java-8 nie oferuje rozwiązania.
Meno Hochschild

Jeszcze raz dziękuję (i za szybką odpowiedź) :)
thomas77

1
Proponuję określić strefę czasową podczas używania LocalDate.now. W przypadku pominięcia bieżąca domyślna strefa czasowa maszyny JVM jest niejawnie stosowana. Ta wartość domyślna może zmieniać się między maszynami / systemami operacyjnymi / ustawieniami, a także może w dowolnym momencie podczas wykonywania przez wywołanie dowolnego kodu setDefault. Zalecam być konkretnym, na przykładLocalDate.now( ZoneId.for( "America/Montreal" ) )
Basil Bourque

1
@GoCrafter_LP Tak, możesz zastosować ThreetenABP symulujący Java-8 lub Joda-Time-Android (od D. Lew) lub moją lib Time4A dla starszych wersji Androida.
Meno Hochschild

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

2
Jaki jest cel czeku (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3)? Istnienie porównań miesiąca i dnia miesiąca wydaje się bezcelowe.
Jed Schaaf

13

Po prostu używam stałej wartości milisekund w roku na swoją korzyść:

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

2
To nie jest dokładna odpowiedź ... rok to nie 3.156e + 10, ale 3.15576e + 10 (kwartał!)
Maher Abuthraa

1
To nie działa, niektóre lata są rokami przestępnymi i mają inną wartość msec
Greg Ennis

12

Jeśli używasz GWT, będziesz ograniczony do korzystania z java.util.Date, oto metoda, która przyjmuje datę jako liczby całkowite, ale nadal używa 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;
}

5

Prawidłowa odpowiedź przy użyciu JodaTime to:

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

Jeśli chcesz, możesz nawet skrócić go do jednej linii. Skopiowałem pomysł z odpowiedzi BrianAgnew , ale uważam, że jest to bardziej poprawne, jak widać z tamtejszych komentarzy (i dokładnie odpowiada na pytanie).


4

Z biblioteką date4j :

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

4

To jest ulepszona wersja powyższego ... biorąc pod uwagę, że chcesz, aby wiek był „int”. ponieważ czasami nie chcesz zapełniać swojego programu wieloma bibliotekami.

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

4

Być może zaskakujące jest to, że nie musisz wiedzieć, ile dni lub miesięcy przypada na rok ani ile dni przypada na te miesiące, podobnie nie musisz wiedzieć o latach przestępnych, sekundach przestępnych ani innych tych rzeczy za pomocą tej prostej, w 100% dokładnej metody:

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

Szukam rozwiązania dla java 6 i 5. To jest proste, ale dokładne.
Jj Tuibeo

3

Spróbuj skopiować ten kod do swojego kodu, a następnie użyj metody, aby uzyskać wiek.

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

Tylko kod odpowiedzi są odradzane. Lepiej byłoby wyjaśnić, dlaczego ten kod może odpowiedzieć na pytanie PO.
рüффп

Właściwie to nie ma sensu ... ale zaktualizuję tylko, aby rozwiązać twój problem
Kevin

3

Używam tego fragmentu kodu do obliczania wieku, mam nadzieję, że to pomaga ... brak bibliotek

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

2

Pola urodzenia i skutku to pola daty:

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

Jest to w zasadzie modyfikacja rozwiązania Johna O bez użycia zdekapitalizowanych metod. Spędziłem sporo czasu próbując zmusić jego kod do pracy w moim kodzie. Może to uratuje tym razem innych.


2
czy możesz to trochę lepiej wyjaśnić? jak to oblicza wiek?
Jonathan S. Fisher

1

A co z tym?

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

To naprawdę urocza sugestia (jeśli nie używasz Jody i nie możesz używać Javy 8), jednak algorytm jest nieco błędny, ponieważ masz 0, aż minie cały pierwszy rok. Musisz więc dodać rok do daty przed rozpoczęciem pętli while.
Dagmar

1

String dateofbirthma datę urodzenia. a format jest dowolny (zdefiniowany w następującym wierszu):

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

Oto jak sformatować:

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

Zmienna ageStrbędzie miała lata.


1

Elegancki, pozornie poprawny wariant rozwiązania Yarona Ronena oparty na różnicy znaczników czasu.

Ja w tym testów jednostkowych do udowodnienia, kiedy i dlaczego to nie jest poprawne . Jest to niemożliwe z powodu (prawdopodobnie) różnej liczby dni przestępnych (i sekund) w jakiejkolwiek różnicy w sygnaturze czasowej. Rozbieżność powinna wynosić max + -1 dzień (i jedną sekundę) dla tego algorytmu, patrz test2 (), podczas gdy rozwiązanie Yarona Ronena oparte na całkowicie stałym założeniu timeDiff / MILLI_SECONDS_YEARmoże różnić się o 10 dni dla 40-latka, ale ten wariant jest również niepoprawny.

Jest to trudne, ponieważ ten ulepszony wariant, wykorzystujący formułę diffAsCalendar.get(Calendar.YEAR) - 1970, zwraca prawidłowe wyniki przez większość czasu, ponieważ liczba lat przestępnych średnio jest taka sama między dwiema datami.

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

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

}

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

Nie jestem pewien, czy naprawdę przetestowałeś ten, czy nie, ale dla innych ta metoda ma jedną wadę. jeśli dzisiaj jest ten sam miesiąc, w którym masz datę urodzenia, a dzisiaj <urodziny, nadal pokazuje rzeczywisty wiek + 1, tj. np. jeśli twoje urodziny są 7 września 1986, a dziś są 1 września 2013, zamiast tego pokaże Ci 27 z 26.
srahul07

2
To nie może być prawdą, ponieważ liczba milisekund w roku NIE JEST STAŁA. Lata przestępne mają jeden dzień więcej, czyli znacznie więcej milisekund niż inne. Dla 40-latka algorytm może zgłosić urodziny 9-10 dni wcześniej, niż to naprawdę jest! Są też sekundy przestępne.
Espinosa

0

Oto kod java do obliczania wieku w roku, miesiącu i dniach.

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

0

Najłatwiejszy sposób bez żadnych bibliotek:

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

1
Ten kod używa kłopotliwych starych klas daty i czasu, które są teraz starsze, zastąpione przez klasy java.time. Zamiast korzystać z nowoczesnych klas wbudowanych w Javie: ChronoUnit.YEARS.between( LocalDate.of( 1968 , Month.MARCH , 23 ) , LocalDate.now() ). Zobacz poprawną odpowiedź
Basil Bourque,

DateUtilsjest biblioteką
Terran

0

W Javie 8 możemy obliczyć wiek osoby za pomocą jednej linii kodu:

public int calCAge(int year, int month,int days){             
    return LocalDate.now().minus(Period.of(year, month, days)).getYear();         
}

wiek w roku czy w miesiącu? co powiesz na dziecko za miesiąc?
gumuruh

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

jak zauważył @sinuhepop "Porównanie DAY_OF_YEAR może prowadzić do błędnych wyników, gdy mamy do czynienia z latami przestępnymi"
Krzysztof Kot

-1
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("");
        }
    }
}

-1
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(<delimiter>)
    // 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(<string>)
    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;
}

Uwaga: format daty to: rrrr-MM-dd. To jest ogólny kod, który jest testowany w jdk7 ...
Jhonie

1
Byłoby pomocne, gdybyś podał kilka komentarzy lub wyjaśnił, jak dokładnie używać tego kodu. Zwykłe zrzucanie kodu jest zwykle odradzane, a osoba zadająca pytanie może nie rozumieć, dlaczego zdecydowałeś się zakodować swoją metodę w ten sposób.
rayryeng

@rayryeng: Jhonie dodał już komentarze w kodzie. Wystarczy to zrozumieć. Prosimy o przemyślenie i przeczytanie przed udzieleniem takiego komentarza.
akshay

@Akshay, to nie było dla mnie oczywiste. Z perspektywy czasu wyglądało na to, że kod został porzucony. Zwykle nie czytam komentarzy. Byłoby miło, gdyby zostały usunięte z ciała i umieszczone osobno jako wyjaśnienie. Jednak to moje preferencje i możemy zgodzić się na to, że nie zgodzimy się tutaj ... To powiedziawszy, zapomniałem nawet, że napisałem ten komentarz, tak jak to było prawie dwa lata temu.
rayryeng

@rayryeng: Powodem tego komentarza było to, że pisanie negatywnych komentarzy zniechęcało ludzi do korzystania z tak fajnego forum. Dlatego powinniśmy ich zachęcać, udzielając pozytywnych komentarzy. Bdw, bez obrazy. Twoje zdrowie!!!
akshay

-1
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.
}

3
Dziękujemy za udział w StackOverflow. Kilka propozycji dla Ciebie. [A] Dołącz dyskusję do swojej odpowiedzi. StackOverflow.com ma być czymś więcej niż tylko zbiorem fragmentów kodu. Na przykład zwróć uwagę, w jaki sposób Twój kod korzysta z nowej struktury java.time, podczas gdy większość innych odpowiedzi używa java.util.Date i Joda-Time. [B] Proszę porównać swoją odpowiedź z podobną odpowiedzią Meno Hochschilda, która również używa java.time. Wyjaśnij, jak twoje jest lepsze, lub atakuj problem z innego punktu widzenia. Lub wycofaj swoje, jeśli nie lepiej.
Basil Bourque

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

-1

Doceniam wszystkie poprawne odpowiedzi, ale to jest odpowiedź kotlin na to samo pytanie

Mam nadzieję, że byłby pomocny dla programistów 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()
    }

Wykonywanie takiej matematyki wydaje się raczej głupie, gdy mamy do dyspozycji wiodące w branży klasy java.time .
Basil Bourque

Żądania OP w Javie.
Terran
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.