Добавить год в календарь Java не работает

пожалуйста, просветите меня на этом:

Я просто пытаюсь добавить 10 лет к текущей дате, а затем вычесть из нее дату истечения срока действия, чтобы вернуть количество лет:

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;
}

когда я отлаживаю это, календарь всегда остается в текущем году.

кого ?

6 ответов


у вас есть проблема с преобразованием int / long: 365 * 24 * 60 * 60 * 1000 Который оценивается в 31536000000 и, следовательно, превышает Integer.MAX_VALUE 2147483647 Это работает:

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 );
        } 

свой расчет max - это неправильно. Ан int не может провести год в миллисе.

лучше заменить на

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

или лучше использовать JodaTime:

DateTime tenYearsLater = new DateTime().plusYears(10);
DateTime expiration = new DateTime(expiration_date.getTime());
Period period = new Period(expiration, tenYearsLater);
return period.getYears();

вот простой пример того, что должно работать.

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

просто не забудьте использовать длинный, чтобы получить время в миллисекундах!


календарь ленив, поэтому он может не пересчитать все остальные поля, пока вы не попросите их. Это сбило меня с толку в отладчике раньше. Что произойдет, если вы System.out.println(ten_year_later);?


я отметил в комментарии, что у вас есть неправильный расчет количества МС в год (по фигу инт/длинный вопрос).

поскольку у вас есть два календаря, каждый из которых может содержать год, почему бы вам не написать свой код так (не скомпилирован, поэтому может содержать опечатки):

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);

предполагая, что это то, что вы действительно хотите ...


количество миллисекунд в году находится далеко за пределами диапазона int, поэтому оба int бросают ten_year_later.getTimeInMillis() - expiration.getTimeInMillis() и расчет 365 * 24 * 60 * 60 * 1000 будет возвращать неверные значения.

на ten_year_later должно быть правильным. Нет необходимости вызывать computeFields, как писал Р. Бемроуз.