noj*_*ive 137 java calendar date
我想在Java方法中将一个年龄作为int返回.我现在有以下内容:getBirthDate()返回Date对象(出生日期;-)):
public int getAge() {
long ageInMillis = new Date().getTime() - getBirthDate().getTime();
Date age = new Date(ageInMillis);
return age.getYear();
}
Run Code Online (Sandbox Code Playgroud)
但是因为getYear()被弃用了,我想知道是否有更好的方法来做到这一点?我甚至不确定这是否正常,因为我还没有进行单元测试.
Bri*_*new 167
查看Joda,它简化了日期/时间计算(Joda也是新标准Java日期/时间apis的基础,因此您将学习一个即将成为标准的API).
编辑:Java 8有一些非常相似的东西,值得一试.
例如
LocalDate birthdate = new LocalDate (1970, 1, 20);
LocalDate now = new LocalDate();
Years age = Years.yearsBetween(birthdate, now);
Run Code Online (Sandbox Code Playgroud)
这就是你想要的那么简单.Java 8之前的东西(正如你所确定的那样)有点不直观.
duf*_*ymo 148
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在每个人都应该使用JDK 8.所有早期版本都已经过了他们的支持生命.
cle*_*tus 42
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
Run Code Online (Sandbox Code Playgroud)
Men*_*ild 39
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
Run Code Online (Sandbox Code Playgroud)
请注意,表达式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
Run Code Online (Sandbox Code Playgroud)
我认为这是一个小错误,但Joda团队对这种奇怪的行为有不同的看法并且不想修复它(很奇怪,因为结束日期的日期小于开始日期所以年份应该是少一个).另见这个封闭的问题.
c)java.util.Calendar等.
为了比较,请参阅其他各种答案.我不建议使用这些过时的类,因为在一些奇特的情况下,结果代码仍然是错误的和/或考虑到原始问题听起来如此简单的事实而过于复杂.在2015年,我们拥有更好的图书馆.
d)关于Date4J:
建议的解决方案很简单,但有时在闰年的情况下会失败.仅评估一年中的某一天并不可靠.
e)我自己的图书馆Time4J:
这类似于Java-8解决方案.只需替换LocalDate
by PlainDate
和ChronoUnit.YEARS
by CalendarUnit.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
Run Code Online (Sandbox Code Playgroud)
小智 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;
}
Run Code Online (Sandbox Code Playgroud)
Lou*_*rda 12
我只是使用一年中常量值的毫秒数来获得优势:
Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
Run Code Online (Sandbox Code Playgroud)
Cra*_*igo 11
如果您正在使用GWT,您将被限制使用java.util.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;
}
Run Code Online (Sandbox Code Playgroud)
注意到您不需要知道一年中有多少天或月或这些月有多少天,这可能令人惊讶,同样,您也不需要知道闰年、闰秒或任何使用这个简单的、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;
}
Run Code Online (Sandbox Code Playgroud)
使用date4j库:
int age = today.getYear() - birthdate.getYear();
if(today.getDayOfYear() < birthdate.getDayOfYear()){
age = age - 1;
}
Run Code Online (Sandbox Code Playgroud)
这是上述版本的改进版本......考虑到您希望年龄为“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;
}
Run Code Online (Sandbox Code Playgroud)
使用JodaTime的正确答案是:
public int getAge() {
Years years = Years.yearsBetween(new LocalDate(getBirthDate()), new LocalDate());
return years.getYears();
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,您甚至可以将其缩短为一行。我从BrianAgnew 的回答中复制了这个想法,但我相信这更正确,正如您从那里的评论中看到的那样(并且它准确地回答了问题)。