Làm cách nào để tính tuổi của ai đó trong Java?


146

Tôi muốn trả về một tuổi trong nhiều năm như một int trong một phương thức Java. Những gì tôi có bây giờ là sau đây nơi getBirthDate () trả về một đối tượng Date (có ngày sinh ;-)):

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

    Date age = new Date(ageInMillis);

    return age.getYear();
}

Nhưng vì getYear () không được dùng nữa nên tôi tự hỏi liệu có cách nào tốt hơn để làm điều này không? Tôi thậm chí không chắc chắn điều này hoạt động chính xác, vì tôi chưa có bài kiểm tra đơn vị tại chỗ (chưa).


Thay đổi suy nghĩ của tôi về điều đó: câu hỏi khác chỉ có xấp xỉ năm giữa các ngày, không phải là một tuổi thực sự chính xác.
cletus

Cho rằng anh ấy trở lại một int, bạn có thể làm rõ ý của bạn khi nói về độ tuổi 'chính xác' không?
Brian Agnew

2
Ngày so với Lịch là một khái niệm cơ bản có thể được thu thập từ việc đọc tài liệu Java. Tôi không thể hiểu tại sao điều này sẽ được nâng cao rất nhiều.
demongolem

@demongolem ??? Ngày & Lịch dễ hiểu?! Không hoàn toàn không. Có hàng trăm câu hỏi về chủ đề ở đây trên Stack Overflow. Dự án Joda-Time đã tạo ra một trong những thư viện phổ biến nhất, để thay thế cho các lớp thời gian rắc rối đó. Sau đó, Sun, Oracle và cộng đồng JCP đã chấp nhận JSR 310 ( java.time ), thừa nhận rằng các lớp kế thừa là vô vọng. Để biết thêm thông tin, xem Hướng dẫn của Oracle .
Basil Bourque

Câu trả lời:


159

JDK 8 làm cho điều này dễ dàng và thanh lịch:

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

Một thử nghiệm JUnit để chứng minh việc sử dụng nó:

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

Mọi người nên sử dụng JDK 8 ngay bây giờ. Tất cả các phiên bản trước đó đã kết thúc cuộc đời hỗ trợ của họ.


10
So sánh DAY_OF_YEAR có thể dẫn đến kết quả sai lầm khi xử lý các năm nhuận.
sinuhepop

1
Biến dateOfBirth phải là đối tượng Date. Làm cách nào để tạo đối tượng Date với ngày sinh?
Erick

Theo quan điểm của chúng tôi là 9 năm và trong trường hợp Java 8 được sử dụng, đây sẽ là giải pháp được sử dụng.
nojevive

JDK 9 là phiên bản sản xuất hiện tại. Đúng hơn bao giờ hết.
duffymo

2
@SteveOh tôi không đồng ý. Tôi thà không chấp nhận nulls, mà thay vào đó sử dụng Objects.requireNonNull.
MC Hoàng đế

170

Hãy xem Joda , đơn giản hóa các tính toán ngày / giờ (Joda cũng là cơ sở của apis ngày / giờ Java tiêu chuẩn mới, vì vậy bạn sẽ học API sớm để trở thành tiêu chuẩn).

EDIT: Java 8 có một cái gì đó rất giống nhau và đáng để kiểm tra.

ví dụ

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

đó là đơn giản như bạn có thể muốn. Các công cụ tiền Java 8 là (như bạn đã xác định) hơi không trực quan.


2
@ HoàngLong: Từ JavaDocs: "Lớp này không đại diện cho một ngày, nhưng tức là một phần nghìn giây vào lúc nửa đêm. Nếu bạn cần một lớp đại diện cho cả ngày, thì Interval hoặc LocalDate có thể phù hợp hơn." Chúng tôi thực sự làm muốn đại diện cho một ngày ở đây.
Jon Skeet

Nếu bạn muốn thực hiện theo cách @JohnSkeet gợi ý, nó sẽ như thế này: Years age = Years.yearsB between (new LocalDate (getBirthDate ()), new LocalDate ());
Fletch

Không biết tại sao tôi lại sử dụng DateUnnight và tôi lưu ý rằng bây giờ nó không dùng nữa. Bây giờ đã thay đổi để sử dụng LocalDate
Brian Agnew


2
@IgorGanapolsky Thực sự khác biệt chính là: Joda-Time sử dụng các hàm tạo trong khi Java-8 và ThreetenBP sử dụng các phương thức nhà máy tĩnh. Đối với một lỗi tinh vi trong cách tính tuổi của Joda, xin vui lòng xem câu trả lời của tôi nơi tôi đã đưa ra một cái nhìn tổng quan về hành vi của các thư viện khác nhau.
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

Vâng, lớp lịch là khủng khiếp. Thật không may, trong công việc đôi khi tôi phải sử dụng nó: /. Cảm ơn Cletus đã đăng bài này
Steve


@Tobbbe Nếu bạn sinh vào ngày 1 tháng 3 trong một năm nhuận, thì sinh nhật của bạn là vào ngày 1 tháng 3 năm sau chứ không phải ngày 2. DAY_OF_YEAR sẽ không hoạt động.
Airsource Ltd

42

Câu trả lời hiện đại và tổng quan

a) Java-8 (java.time-gói)

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

Lưu ý rằng biểu thức LocalDate.now()có liên quan ngầm đến múi giờ hệ thống (thường bị người dùng bỏ qua). Để rõ ràng, tốt hơn là sử dụng phương pháp quá tải now(ZoneId.of("Europe/Paris"))chỉ định múi giờ rõ ràng (ví dụ "Châu Âu / Paris"). Nếu múi giờ hệ thống được yêu cầu thì sở thích cá nhân của tôi là viết LocalDate.now(ZoneId.systemDefault())để làm cho mối quan hệ với múi giờ hệ thống rõ ràng hơn. Đây là nỗ lực viết nhiều hơn nhưng làm cho việc đọc dễ dàng hơn.

b) Thời gian Joda

Xin lưu ý rằng giải pháp Joda-Time được đề xuất và chấp nhận mang lại kết quả tính toán khác nhau cho các ngày được hiển thị ở trên (một trường hợp hiếm), cụ thể là:

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

Tôi coi đây là một lỗi nhỏ nhưng nhóm Joda có quan điểm khác về hành vi kỳ lạ này và không muốn sửa nó (kỳ lạ vì ngày kết thúc của ngày nhỏ hơn ngày bắt đầu nên năm nên một ít hơn). Xem thêm vấn đề kín này .

c) java.util.CalWiki, v.v.

Để so sánh xem các câu trả lời khác nhau. Tôi hoàn toàn không khuyên bạn nên sử dụng các lớp lỗi thời này bởi vì mã kết quả vẫn bị lỗi trong một số trường hợp kỳ lạ và / hoặc quá phức tạp khi xem xét thực tế rằng câu hỏi ban đầu nghe có vẻ đơn giản. Trong năm 2015 chúng tôi có thư viện thực sự tốt hơn.

d) Giới thiệu về Date4J:

Giải pháp đề xuất rất đơn giản nhưng đôi khi sẽ thất bại trong trường hợp năm nhuận. Chỉ đánh giá ngày trong năm là không đáng tin cậy.

e) Thư viện riêng của tôi Time4J :

Điều này hoạt động tương tự như giải pháp Java-8. Chỉ cần thay thế LocalDatebởi PlainDateChronoUnit.YEARSbởi CalendarUnit.YEARS. Tuy nhiên, nhận được "ngày hôm nay" đòi hỏi một tham chiếu múi giờ rõ ràng.

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
Cảm ơn bạn đã có phiên bản Java 8! Tiết kiệm cho tôi một chút thời gian :) Bây giờ tôi chỉ cần tìm ra cách trích xuất các tháng còn lại. Ví dụ: 1 năm và 1 tháng. :)
thomas77

2
@ thomas77 Cảm ơn bạn đã trả lời, kết hợp nhiều năm và tháng (và có thể cả ngày) có thể được thực hiện bằng cách sử dụng `java.time.Period 'trong Java-8. Nếu bạn cũng muốn tính đến các đơn vị khác như giờ thì Java-8 không cung cấp giải pháp.
Meno Hochschild

Cảm ơn bạn một lần nữa (và đã phản hồi nhanh) :)
thomas77

1
Tôi đề nghị chỉ định một múi giờ khi sử dụng LocalDate.now. Nếu bỏ qua múi giờ mặc định hiện tại của JVM thì hoàn toàn được áp dụng. Mặc định đó có thể thay đổi giữa các máy / HĐH / cài đặt và cũng có thể bất cứ lúc nào trong thời gian chạy bằng bất kỳ cuộc gọi mã nào setDefault. Tôi khuyên bạn nên cụ thể, chẳng hạn nhưLocalDate.now( ZoneId.for( "America/Montreal" ) )
Basil Bourque

1
@GoCrafter_LP Có, bạn có thể áp dụng ThreetenABP mô phỏng Java-8 hoặc Joda-Time-Android (từ D. Lew) hoặc Time4A lib của tôi cho các phiên bản Android cũ hơn như vậy.
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
Mục đích của việc kiểm tra là (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3)gì? Dường như vô nghĩa với sự tồn tại của các so sánh giữa tháng và ngày.
Jed Schaaf

12

Nếu bạn đang sử dụng GWT, bạn sẽ bị giới hạn sử dụng java.util.Date, đây là phương pháp lấy ngày làm số nguyên, nhưng vẫn sử dụng 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;
}

12

Tôi chỉ đơn giản sử dụng mili giây trong một năm giá trị không đổi để lợi thế của tôi:

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

2
Đây không phải là câu trả lời chính xác ... năm không phải là 3.156e + 10 mà là 3.15576e + 10 (ngày quý!)
Maher Abuthraa

1
Điều này không hoạt động, một số năm là năm nhuận và có giá trị msec khác nhau
Greg Enni

5

Câu trả lời đúng khi sử dụng JodaTime là:

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

Bạn thậm chí có thể rút ngắn nó thành một dòng nếu bạn muốn. Tôi đã sao chép ý tưởng từ câu trả lời của BrianAgnew , nhưng tôi tin rằng điều này đúng hơn khi bạn thấy từ các bình luận ở đó (và nó trả lời chính xác câu hỏi).


4

Với thư viện date4j :

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

4

Đây là phiên bản cải tiến của phiên bản trên ... xem xét rằng bạn muốn tuổi là 'int'. bởi vì đôi khi bạn không muốn lấp đầy chương trình của mình với một loạt các thư viện.

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

Có lẽ đáng ngạc nhiên khi lưu ý rằng bạn không cần biết có bao nhiêu ngày hoặc tháng trong một năm hoặc bao nhiêu ngày trong những tháng đó, tương tự, bạn không cần biết về năm nhuận, giây nhuận hoặc bất kỳ của những thứ đó bằng phương pháp đơn giản, chính xác 100% này:

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

Tôi đang tìm giải pháp cho java 6 và 5. Điều này đơn giản nhưng chính xác.
Jj Tuibeo

3

Cố gắng sao chép mã này trong mã của bạn, sau đó sử dụng phương pháp để lấy tuổi.

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

Mã chỉ trả lời được khuyến khích. Sẽ tốt hơn để giải thích tại sao mã này có thể giải quyết câu hỏi OP.
рüффп

Thực sự không có trí tuệ .. nhưng sẽ cập nhật chỉ để giải quyết mối quan tâm của bạn
Kevin

3

Tôi sử dụng đoạn mã này để tính tuổi, Hy vọng điều này sẽ giúp .. không có thư viện nào được sử dụng

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

Các trường sinh và hiệu ứng đều là các trường ngày:

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

Về cơ bản, đây là bản sửa đổi của giải pháp John O mà không sử dụng các phương pháp khấu hao. Tôi đã dành một khoảng thời gian hợp lý để cố gắng để mã của anh ấy hoạt động trong mã của tôi. Có lẽ điều này sẽ tiết kiệm cho người khác thời gian đó.


2
bạn có thể giải thích điều này tốt hơn một chút? Làm thế nào để tính tuổi này?
Jonathan S. Fisher

1

Cái này thì sao?

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

Đây là một gợi ý thực sự dễ thương (khi bạn không sử dụng Joda và không thể sử dụng Java 8) tuy nhiên thuật toán hơi sai vì bạn là 0 cho đến khi toàn bộ năm đầu tiên trôi qua. Vì vậy, bạn cần thêm một năm vào ngày trước khi bạn bắt đầu vòng lặp while.
Dagmar

1

String dateofbirthcó ngày sinh và định dạng là bất cứ điều gì (được xác định trong dòng sau):

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

Đây là cách định dạng:

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

Biến ageStrsẽ có năm.


1

Biến thể thanh lịch, dường như chính xác , khác biệt dựa trên dấu thời gian của giải pháp Yaron Ronen.

Tôi đang bao gồm một bài kiểm tra đơn vị để chứng minh khi nào và tại sao nó không đúng . Không thể do (có thể) số ngày nhuận khác nhau (và giây) trong bất kỳ chênh lệch dấu thời gian nào. Sự khác biệt phải là tối đa + -1 ngày (và một giây) cho thuật toán này, xem test2 (), trong khi giải pháp Yaron Ronen dựa trên giả định hoàn toàn không đổi timeDiff / MILLI_SECONDS_YEARcó thể khác nhau 10 ngày đối với một người 40 tuổi, tuy nhiên biến thể này cũng không chính xác.

Đó là khó khăn, bởi vì biến thể được cải tiến này, sử dụng công thức diffAsCalendar.get(Calendar.YEAR) - 1970, trả về kết quả chính xác hầu hết thời gian, vì số năm nhuận trung bình giống nhau giữa hai ngày.

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

Không chắc chắn liệu bạn có thực sự thử nghiệm cái này hay không, nhưng đối với những người khác, phương pháp này có một lỗ hổng. nếu hôm nay là cùng tháng với ngày sinh của bạn và hôm nay <sinh nhật, nó vẫn hiển thị tuổi thực tế + 1, ví dụ: nếu ngày của bạn là ngày 7 tháng 9 năm 1986 và hôm nay là ngày 1 tháng 9 năm 2013, nó sẽ hiển thị cho bạn 27 thay vào đó ngày 26.
srahul07

2
Điều này không thể đúng vì số mili giây trong một năm là KHÔNG CÓ. Năm nhuận có thêm một ngày, tức là nhiều mili giây hơn những năm khác. Đối với một người 40 tuổi, thuật toán của bạn có thể báo cáo sinh nhật sớm hơn 9 - 10 ngày thì thực sự là vậy! Cũng có những giây nhuận.
Espinosa

0

Dưới đây là mã java để tính tuổi theo năm, tháng và ngày.

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

Cách dễ nhất mà không có bất kỳ thư viện:

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

1
Mã này sử dụng các lớp thời gian cũ rắc rối mà bây giờ là di sản, được thay thế bởi các lớp java.time. Thay vào đó, hãy sử dụng các lớp hiện đại được tích hợp vào Java : ChronoUnit.YEARS.between( LocalDate.of( 1968 , Month.MARCH , 23 ) , LocalDate.now() ). Xem câu trả lời đúng
Basil Bourque

DateUtilslà một thư viện
Terran

0

Với Java 8, chúng ta có thể tính tuổi của một người bằng một dòng mã:

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

tuổi trong năm hay trong tháng? Em bé tháng nào?
gumuruh

0

Tôi đánh giá cao tất cả các câu trả lời đúng nhưng đây là câu trả lời kotlin cho cùng một câu hỏi

Tôi hy vọng sẽ hữu ích cho các nhà phát triển 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()
    }

Điều này có vẻ khá ngớ ngẩn khi làm toán như vậy khi chúng ta có các lớp java.time dẫn đầu ngành theo ý của chúng ta.
Basil Bourque

Yêu cầu OP trong Java.
Terran

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

như @sinuhepop nhận thấy "Sự so sánh DAY_OF_YEAR có thể dẫn đến kết quả sai lầm khi xử lý các năm nhuận"
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;
}

Lưu ý: Định dạng ngày là: yyyy-MM-dd. Đây là một mã chung được thử nghiệm trong jdk7 ...
Jhonie

1
Nó sẽ giúp nếu bạn cung cấp một số ý kiến ​​hoặc giải thích chính xác cách sử dụng mã này. Đơn giản là việc bán phá giá mã thường không được khuyến khích và người hỏi có thể không hiểu các lựa chọn của bạn đằng sau lý do tại sao bạn quyết định viết mã phương pháp của mình theo cách này.
rayryeng

@rayryeng: Jhonie đã thêm ý kiến ​​trong mã. Điều đó là đủ để hiểu. Hãy suy nghĩ và đọc trước khi đưa ra nhận xét như vậy.
akshay 30/03/2016

@Akshay điều đó không rõ ràng với tôi. Nhìn lại có vẻ như anh ta đã đổ mã. Tôi thường không đọc bình luận. Sẽ tốt hơn nếu những cái đó được gỡ bỏ khỏi cơ thể và được đặt riêng như một lời giải thích. Đó là sở thích của tôi và chúng tôi có thể đồng ý không đồng ý ở đây .... Điều đó nói rằng, tôi đã quên tôi thậm chí đã viết bình luận này vì nó đã gần hai năm trước.
rayryeng

@rayryeng: Lý do đằng sau bình luận này là, viết bình luận tiêu cực không khuyến khích mọi người sử dụng một diễn đàn tốt đẹp như vậy. Vì vậy, chúng ta nên khuyến khích họ bằng cách đưa ra những bình luận tích cực. Bdw, không có hành vi phạm tội. Chúc mừng !!!
akshay 30/03/2016

-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
Cảm ơn bạn đã tham gia StackOverflow. Một vài gợi ý cho bạn. [A] Vui lòng bao gồm một số cuộc thảo luận với Câu trả lời của bạn. StackOverflow.com có ​​nghĩa là nhiều hơn một bộ sưu tập đoạn mã. Ví dụ: lưu ý cách mã của bạn đang sử dụng khung java.time mới trong khi hầu hết các câu trả lời khác đang sử dụng java.util.Date và Joda-Time. [B] Vui lòng đối chiếu Câu trả lời của bạn với Câu trả lời tương tự của Meno Hochschild cũng sử dụng java.time. Giải thích làm thế nào bạn tốt hơn hoặc tấn công một góc khác vào vấn đề. Hoặc rút lại của bạn nếu không tốt hơn.
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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.