我如何计算Java的年龄?
我想在Java方法中将年数作为int返回。 我现在拥有的是getBirthDate()返回一个Date对象(出生date;-)):
public int getAge() { long ageInMillis = new Date().getTime() - getBirthDate().getTime(); Date age = new Date(ageInMillis); return age.getYear(); }
但由于getYear()已弃用,我想知道是否有更好的方法来做到这一点? 我甚至不确定这个工作是否正确,因为我还没有到位的unit testing。
查看Joda ,它简化了date/时间计算(Joda也是新的标准Javadate/时间API的基础,因此您将学习一个即将成为标准的API)。
编辑:Java 8有一些非常相似的东西 ,值得一试。
例如
LocalDate birthdate = new LocalDate (1970, 1, 20); LocalDate now = new LocalDate(); Years age = Years.yearsBetween(birthdate, now);
这是尽可能简单,你可以想要的。 Java之前的东西是(如你所认识的)有点不直观。
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; } } }
一个JUnittesting来演示它的使用:
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); } }
现在每个人都应该使用JDK 8。 所有早期的版本已经过了他们的支持生命的结束。
Calendar now = Calendar.getInstance(); Calendar dob = Calendar.getInstance(); dob.setTime(...); if (dob.after(now)) { throw new IllegalArgumentException("Can't be born in the future"); } int year1 = now.get(Calendar.YEAR); int year2 = dob.get(Calendar.YEAR); int age = year1 - year2; int month1 = now.get(Calendar.MONTH); int month2 = dob.get(Calendar.MONTH); if (month2 > month1) { age--; } else if (month1 == month2) { int day1 = now.get(Calendar.DAY_OF_MONTH); int day2 = dob.get(Calendar.DAY_OF_MONTH); if (day2 > day1) { age--; } } // age is now correct
现代的答案和概述
a)Java-8(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()
expression式与系统时区(用户经常忽略LocalDate.now()
隐含相关。 为了清楚起见, now(ZoneId.of("Europe/Paris"))
使用重载方法now(ZoneId.of("Europe/Paris"))
指定明确的时区(此处以“Europe / Paris”为例)通常会更好。 如果系统时区被请求,那么我的个人偏好是编写LocalDate.now(ZoneId.systemDefault())
来使系统时区的关系更清晰。 这是更多的写作努力,但使阅读更容易。
b)乔达时间
请注意,提出并接受的Joda-Time解决scheme在上述date(极less数情况下)会产生不同的计算结果,即:
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团队对这种奇怪的行为有不同的看法,不想修复它(奇怪,因为结束date的月份比开始date小,所以年份应该是less一个)。 另见这个封闭的问题 。
c)java.util.Calendar等
为了比较,请参阅各种其他答案。 我不会推荐使用这些过时的类,因为在某些外来的情况下,由此产生的代码仍然是错误的,或者考虑到原始问题听起来如此简单的事实,所以太复杂。 在2015年,我们有更好的图书馆。
d)关于Date4J:
提出的解决scheme很简单,但在闰年的情况下有时会失败。 只是评估一年的一天是不可靠的。
e)我自己的图书馆Time4J :
这与Java-8解决scheme类似。 只需用CalendarUnit.YEARS
replacePlainDate
LocalDate
和ChronoUnit.YEARS
。 但是,获得“今天”需要明确的时区参考。
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; }
如果你正在使用GWT,你将被限制为使用java.util.Date,这是一个将date作为整数的方法,但仍然使用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; }
我简单地用一年的毫秒数来衡量我的优势:
Date now = new Date(); long timeBetween = now.getTime() - age.getTime(); double yearsBetween = timeBetween / 3.156e+10; int age = (int) Math.floor(yearsBetween);
用date4j库:
int age = today.getYear() - birthdate.getYear(); if(today.getDayOfYear() < birthdate.getDayOfYear()){ age = age - 1; }
使用JodaTime的正确答案是:
public int getAge() { Years years = Years.yearsBetween(new LocalDate(getBirthDate()), new LocalDate()); return years.getYears(); }
如果你喜欢,你甚至可以把它缩短成一行。 我从BrianAgnew的回答中复制了这个想法,但是我相信这样做更正确,正如您从评论中看到的那样(并且完全回答了问题)。
尝试在你的代码中复制这一个,然后使用该方法来获得年龄。
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; }
字段的出生和效果都是date字段:
Calendar bir = Calendar.getInstance(); bir.setTime(birth); int birthNm = bir.get(Calendar.DAY_OF_YEAR); int birthYear = bir.get(Calendar.YEAR); Calendar eff = Calendar.getInstance(); eff.setTime(effect);
这基本上是对John O的解决scheme进行修改而不使用折旧方法。 我花了相当多的时间试图让他的代码在我的代码中工作。 也许这会节省时间。
这是上面的一个改进版本…考虑到你想年龄是一个“整数”。 因为有时你不想用一堆库来填充你的程序。
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; }
我使用这段代码进行年龄计算,希望这有助于..不使用库
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 ; }
String
dateofbirth
有出生date。 格式是什么(定义在下面一行):
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());
variablesageStr
将有这些年。
优雅, 看似正确 ,时间戳差异基于亚龙Ronen解决scheme的变种。
我包括一个unit testing来certificate何时以及为什么不正确 。 在任何时间戳差异中,不可能由于(可能)不同数量的闰日(和秒)。 这个algorithm的差异应该是max + -1天(和1秒),参见test2(),而基于完全不变的假设timeDiff / MILLI_SECONDS_YEAR
Yaron Ronen解决scheme对于一个40岁的人可能会有10天的不同,不过这个变体是也不正确。
这是棘手的,因为这个改进的变体,使用公式diffAsCalendar.get(Calendar.YEAR) - 1970
,大多数时间返回正确的结果,闰年的平均数相同的两个date之间。
/** * 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; }
也许令人惊讶的是,你不需要知道一年中有多less天或几个月,或者那几个月有多less天,同样,你也不需要知道闰年,闰秒或任何这个简单的,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; }
/** * 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; }
这里是计算年,月和日的年龄的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); }
没有任何库的最简单的方法:
long today = new Date().getTime(); long diff = today - birth; long age = diff / DateUtils.YEAR_IN_MILLIS;
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(<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; }
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. }
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; }