tags:

views:

130

answers:

6

Please enlight me on this :

I'm simply trying to add 10 years to the current date then substract an expiration date from it to return the number of years:

public int getMaxYears() {
  int max = 0;
  Calendar ten_year_later = Calendar.getInstance();
  ten_year_later.setTime(new Date());
  ten_year_later.add(Calendar.YEAR, 10);
  Calendar expiration = Calendar.getInstance();
  expiration.setTime(expiration_date);
  max = (int) (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000);
  return max;
}

When I debug this, the calendar always stay at the current year.

Anyone ?

A: 

Calendar is lazy, so it might not recalculate all the other fields until you ask for them. That's thrown me off in the debugger before. What happens if you System.out.println(ten_year_later);?

Paul Tomblin
The `getTimeInMillis()` should already have updated the fields -as every other `get` method of `Calendar`.
BalusC
@Paul Tomblin : Even if I call ten_year_later.getTimeInMillis() ? max is always 0 cause the expiration_date after than today.
elblanco
No, I was talking about what you see in the debugger before you call getTimeInMillis().
Paul Tomblin
+5  A: 

Your calculation of max is wrong. An int cannot hold a year in millis.

Rather replace it by

max = ten_year_later.get(Calendar.YEAR) - expiration.get(Calendar.YEAR);

Or better, use JodaTime:

DateTime tenYearsLater = new DateTime().plusYears(10);
DateTime expiration = new DateTime(expiration_date.getTime());
Period period = new Period(expiration, tenYearsLater);
return period.getYears();
BalusC
This will not work! 2020-01-01 - 2010-12-31 = 10. It should give 9 + 1 day, so 9 years;
elblanco
@elblanco: See my comment on stacker's answer.
BalusC
+1 I fully agree that it should be calculated as you pointed out.
stacker
+1 for mentioning Joda Time!
CoolBeans
+6  A: 

You have a problem with int / long conversion: 365 * 24 * 60 * 60 * 1000 Which evaluates to 31536000000 and therefore exceeds Integer.MAX_VALUE 2147483647 This works:

public static void main(String[] args) {
          Calendar ten_year_later = Calendar.getInstance();
          System.out.println( ten_year_later.getTime() );
          ten_year_later.setTime(new Date()); 
          ten_year_later.add(Calendar.YEAR, 10);
          System.out.println( ten_year_later.getTime() );
          Calendar expiration = Calendar.getInstance(); 
          expiration.setTime(expiration.getTime()); 
          long max = (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000L); 
          System.out.println( "max " + max );
        } 
stacker
+1: I think this is better for the case the OP would like to round down on years instead of round up. The OP only have to keep in mind that a year doesn't necessarily have 365 days.
BalusC
Right on! Thank you!
elblanco
A: 

Here's a simple example of what should work.

Calendar cal = new GregorianCalendar();
cal.setTime(new Date());
cal.add(Calendar.YEAR, yearsToAdd);
Date retDate = cal.getTime();

Just remember to use a long to get the time in milliseconds!

Bryan James
A: 

The number of milliseconds in a year is well outside the range of an int, so both the int cast of ten_year_later.getTimeInMillis() - expiration.getTimeInMillis() and the calculation 365 * 24 * 60 * 60 * 1000 will evaluate to incorrect values.

The ten_year_later should be correct. There is no need to invoke computeFields as R. Bemrose wrote.

jarnbjo
+1  A: 

I've noted in a comment that you have an incorrect calculation for number of millis in a year (nevermind the int/long issue).

Since you have two calendars, each of which can keep a year, why don't you write your code like this (not compiled, so may contain typos):

Calendar cal1 = Calendar.newInstance();   // this will use current time
cal1.add(Calendar.YEAR, 10);
Calendar cal2 = Calendar.newInstance();
cal2.setDate(expiration);
return cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);

Assuming that's what you really want ...

Anon