I want to return an age in years as an int in a Java method. What I have now is the following where getBirthDate() returns a Date object (with the birth date ;-)):
Elegant, seemingly correct, timestamp difference based variant of Yaron Ronen solution.
I am including a unit test to prove when and why it is not correct. It is impossible due (to possibly) different number of leap days (and seconds) in any timestamp difference. The discrepancy should be max +-1 day (and one second) for this algorithm, see test2(), whereas Yaron Ronen solution based on completely constant assumption of timeDiff / MILLI_SECONDS_YEAR
can differ 10 days for a 40ty year old, nevertheless this variant is incorrect too.
It is tricky, because this improved variant, using formula diffAsCalendar.get(Calendar.YEAR) - 1970
, returns correct results most of the time, as number of leap years in on average same between two dates.
/**
* 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));
}
}