I must be doing something fundamentally wrong here. I’ve got very simple code:
private static final long MILLIS_PER_YEAR = 1000 * 60 * 60 * 24 * 365;
//...
public long getAge() {
long millis = System.currentTimeMillis() - this.getBirthdate().getTime();
System.out.println("Computed age: " + (millis / MILLIS_PER_YEAR) + ", birthdate=" + this.getBirthdate() + ", birthdateMillis="
+ this.getBirthdate().getTime() + ", now=" + new Date() + ", nowMillis=" + System.currentTimeMillis()
+ ", elapsedMillis=" + millis);
return millis / MILLIS_PER_YEAR;
}
…but it’s giving some completely incorrect output:
Computed age: 248, birthdate=2001-01-01 10:00:00.0, birthdateMillis=978307200000, now=Fri Aug 10 16:56:48 EST 2012, nowMillis=1344581808173, elapsedMillis=366274608173
Computed age: 184, birthdate=2004-01-01 10:00:00.0, birthdateMillis=1072915200000, now=Fri Aug 10 16:56:48 EST 2012, nowMillis=1344581808173, elapsedMillis=271666608173
If I run the same computation manually (or by using Google), I get the correct result (within a reasonable allowance, due to the fact that there are slightly more than 365 days in a real year).
How is it that the same math is producing such nonsensical output in this code?
The value of
MILLIS_PER_YEARis wrong. It’s1471228928instead of the desired31536000000.Look at the calculation of the value: all participating values are
intvalues (numeric, non-decimal constants areint-values by default in Java). This means that the result of the calculation will be anintvalue as well. But the desired value is bigger than anintcan hold, so you’ll have an overflow.To ensure that the caluclation is done on
longvalues, simply make at least one of the values a long (by appending theLsuffix):