我如何用 Java 计算某人的年龄?

我想在 Java 方法中以年为单位返回一个整型数。 我现在得到的是如下代码,getBirthDate ()返回一个 Date 对象(带有出生日期; ——) :

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


Date age = new Date(ageInMillis);


return age.getYear();
}

但是,由于 getYear ()已被弃用,我想知道是否有更好的方法来实现这一点?我甚至不确定这是否正确,因为我还没有适当的单元测试。

376625 次浏览

JDK 8使这一过程变得简单而优雅:

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

一个 JUnit 测试来演示它的用法:

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

现在每个人都应该在使用 JDK8了,所有早期的版本都已经过了它们的支持生命周期。

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

看看 Joda,它简化了日期/时间计算(Joda 也是新的标准 Java 日期/时间 apis 的基础,因此您将学习一个即将成为标准的 API)。

例如:。

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

在 Java8之前的东西(正如你已经指出的)有些不直观。

编辑: Java8有 非常相似的东西,值得一看。

编辑: 这个答案早于 Java8的日期/时间类,不再是最新的了。

使用 约会4j库:

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

如果您使用的是 GWT,那么您将仅限于使用 java.util。Date,这里是一个将日期作为整数的方法,但仍然使用 java.util。日期:

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

“出生”和“效果”字段都是日期字段:

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

这基本上是修改了约翰 O 的解决方案,没有使用折旧方法。我花了相当多的时间试图让他的代码在我的代码中起作用。也许那时候这能救其他人。

这是上面那个的改进版本... ... 考虑到您希望 age 是一个“ int”。因为有时候你不想用一堆库来填充你的程序。

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

尝试在代码中复制这个,然后使用该方法获取年龄。

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

这个怎么样?

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

使用 JodaTime的正确答案是:

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

如果你愿意,你甚至可以把它缩短成一行。我抄袭了 BrianAgnew 的回答的想法,但是我相信这个想法更正确,因为你可以从那里的评论中看到(它正好回答了这个问题)。

Stringdateofbirth有出生日期。格式是什么(定义在下面一行) :

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

以下是如何格式化:

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

变量 ageStr将有年份。

雅致,似乎是对的,基于时间戳差异的变体 YaronRonen 解决方案。

我包括一个 单元测试,以证明何时和为什么它是不正确的。这是不可能的,因为(可能)不同的闰日(和秒)在任何时间戳的差异。对于这个算法,差异应该是最大 +-1天(和1秒) ,参见 test2() ,而基于完全恒定的 timeDiff / MILLI_SECONDS_YEAR假设的 Yaron Ronen 解对于40岁的人可以有10天的差异,然而这个变体也是不正确的。

这很棘手,因为这个改进的变量使用公式 diffAsCalendar.get(Calendar.YEAR) - 1970,在大多数情况下返回正确的结果,因为两个日期之间的平均闰年数相同。

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


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

现代的回答和概述

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

注意,表达式 LocalDate.now()隐式地与系统时区相关(用户经常忽略这一点)。为了清楚起见,通常最好使用重载方法 now(ZoneId.of("Europe/Paris"))指定一个明确的时区(例如“ Europe/Paris”)。如果请求系统时区,那么我的个人偏好是编写 LocalDate.now(ZoneId.systemDefault()),以使与系统时区的关系更清楚。这是更多的写作努力,但使阅读更容易。

B) Joda-Time

请注意,建议和接受的 Joda-Time 解决方案对上述日期产生了不同的计算结果(一种罕见的情况) ,即:

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

我认为这只是一个小错误,但 Joda 团队对这种奇怪的行为有不同的看法,并不想修复它(奇怪是因为月结束日期比开始日期小,所以一年应该少一个)。也请看这封闭的 问题

C) java.util.Calendar 等。

为了进行比较,请看其他各种答案。我根本不建议使用这些过时的类,因为在一些特殊情况下,结果代码仍然容易出错,而且/或者考虑到最初的问题听起来很简单,所以太复杂了。在2015年,我们有了更好的图书馆。

D)关于日期4J:

提出的解决方案很简单,但在闰年的情况下有时会失败。仅仅评估一年中的某一天是不可靠的。

E)我自己的图书馆 Time4J :

这与 Java-8解决方案类似。用 PlainDate代替 LocalDate,用 CalendarUnit.YEARS代替 ChronoUnit.YEARS。但是,获取“ today”需要显式的时区引用。

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

你不需要知道一年中有多少天或者多少个月,或者这些月份中有多少天,这可能会让人感到惊讶。同样,你也不需要知道闰年、闰秒,或者其他任何东西,使用这个简单的、100% 准确的方法:

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

我只是简单地使用一年中的毫秒值作为我的优势:

Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
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.
}

下面是以年、月和天计算年龄的 Java 代码。

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

我使用这段代码计算年龄,希望这有助于. . 没有使用库

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

没有图书馆的最简单方法:

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

使用 Java8,我们可以用一行代码计算一个人的年龄:

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

谢谢你的正确回答,但这是同一个问题的 Kotlin 答案

我希望对 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()
}

Kotlin 的简单解决方案。

  fun getAgeOfUser(date: String?) : Int {
if(date.isNullOrEmpty()) return 0
val calendar = Calendar.getInstance()
val cYear = calendar.get(Calendar.YEAR)
val cDay = calendar.get(Calendar.DAY_OF_YEAR)


val dob = Calendar.getInstance()
dob.timeInMillis = date.toLong()
val bYear = dob.get(Calendar.YEAR)
val bDay = dob.get(Calendar.DAY_OF_YEAR)


var age = cYear - bYear
if(cDay < bDay) age--
return age
}