You are using outmoded classes.
java.time
Java 8 and later comes with the java.time framework built-in.
LocalDate
The LocalDate
class represents a date-only value, without time-of-day and without time zone. But time zone is critical it determining "today". For any given moment the date may vary around the world by time zone. A few moments after midnight in Paris is still “yesterday” in Montréal.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
Build a date-of-birth from your user input.
LocalDate dob = LocalDate.of ( 1955 , 1 , 2 );
Or parse a string compliant with the ISO 8601 standard.
LocalDate dob = LocalDate.parse( "1955-01-02" );
Or use a DateTimeFormatter
to help parse a different string.
If you have a java.util.Date
object on hand use a new method added to that old class for conversion to java.time: java.util.Date::toInstant
. An Instant
is a moment on the timeline in UTC.
Instant instant = myJavaUtilDate.toInstant();
Apple a time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Extract a LocalDate
.
LocalDate localDate = zdt.toLocalDate();
Period
Age is just one kind of elapsed time, a span of time. In java.time, the Period
class represents a span of time tracked in terms of years, months, and days.
Period age = Period.between ( dob , today );
Get years from Period
Ask for the years if that is all you want.
int years = age.getYears ();
Beware that getYears
is not normalized to the full number of years as you may intuit. Depending on how a Period
is constructed, you may get an unexpected result. Another approach is to call toTotalMonths()
and divide by 12 (twelve months to a year). See both approaches in this quick example; compare y
and y2
.
Period p = Period.ofMonths ( 25 );
int y = p.getYears ();
long y2 = ( ( p.toTotalMonths () ) / 12 );
System.out.println ( "p: " + p + " | y: " + y + " | y2: " + y2 );
p: P25M | y: 0 | y2: 2
Even better, force the Period
object to be normalized to a full count of years then months then days. Well, not exactly force the object: Because of immutable objects, you are actually instantiating a new object based on the original object’s values.
So while our age
object happens to already be normalized because of its particular construction, it might be a good habit to always call normalized
.
Period age = Period.between ( dob , today ).normalized();
Dump to console. By default, the Period::toString
method generates a string according to the ISO 8601 standard for Durations such as P61Y2M27D
seen here.
System.out.println ( "zoneid: " + zoneId + " | today: " + today + " | dob: " + dob + " | age: " + age + " | years: " + years );
zoneid: America/Montreal | today: 2016-03-29 | dob: 1955-01-02 | age: P61Y2M27D | years: 61
Convert int
to Integer
Lastly, if you need an object rather than a primitive, convert int
to Integer
.
Integer yearsObj = Integer.valueOf ( years );