Я просто пытаюсь добавить 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;
}
Когда я отлаживаю это, календарь всегда остается в текущем году.
Кто угодно ?
Какой календарь? ten_year_later или срок действия? Paul Tomblin 07.10.2010
@Paul Tomblin: ten_year_later ... Я отредактирую вопрос. codea 07.10.2010
Также: год не 365 дней, он должен учитывать високосные годы. Для грубых расчетов подойдет 365,25, но для реальных расчетов нужно что-то, что знает правила... вроде Календаря. Anon 07.10.2010
@Анон: Я знаю. Спасибо, но вопрос не в этом. codea 07.10.2010
Я бы предложил использовать библиотеку JodaTime для всех ваших потребностей в расчете даты. Erick Robertson 07.10.2010
Возможно, но это всего лишь одна из нескольких логических ошибок в коде. Суть моего комментария в том, что у вас есть инструмент для манипулирования датами, но вы пытаетесь манипулировать ими вне этого инструмента. Смотрите мой ответ, если вам нужны подробные инструкции. Anon 07.10.2010
У вас проблема с преобразованием int/long: 365 * 24 * 60 * 60 * 1000, что оценивается как 31536000000 и, следовательно, превышает Integer.MAX_VALUE 2147483647. Это работает:
Ваш расчет 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();
Ответ 3 · рейтинг 5 · Bryan James
Вот простой пример того, что должно работать.
Calendar cal = new GregorianCalendar();
cal.setTime(new Date());
cal.add(Calendar.YEAR, yearsToAdd);
Date retDate = cal.getTime();
Просто не забудьте использовать long, чтобы получить время в миллисекундах!
Ответ 4 · рейтинг 1 · Paul Tomblin
Календарь ленив, поэтому он может не пересчитывать все остальные поля, пока вы их не попросите. Это сбило меня с толку в отладчике раньше. Что произойдет, если вы System.out.println(ten_year_later);?
Ответ 5 · рейтинг 1 · Anon
Я отметил в комментарии, что у вас неправильный расчет количества милли в год (не говоря уже о проблеме int/long).
Поскольку у вас есть два календаря, в каждом из которых может храниться год, почему бы вам не написать свой код так (не скомпилированный, поэтому может содержать опечатки):
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);
Предположим, что вы действительно этого хотите...
Ответ 6 · рейтинг 1 · Basil Bourque
tl;dr
Используйте современные классы java.time. Можно сделать в один лайнер (не то, чтобы я рекомендовал это).
Современный подход использует классы java.time, которые заменили устаревшие классы даты и времени, такие как Calendar.
Обычной конкретной реализацией Calendar является GregorianCalendar. Теперь это заменено на ZonedDateTime. Вы можете конвертировать туда и обратно, вызывая новые методы в старых классах.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;
Добавьте десять лет.
ZonedDateTime zdtLater = zdtNow.plusYears( 10 ) ;
Рассчитайте время, прошедшее в годах между датами этих двух моментов.
Period p = Period.between(
zdtExpiration.toLocalDate() ,
zdtLater.toLocalDate()
) ;
Опросите количество полных лет.
int yearsElapsed = p.getYears() ;
О java.time
java.time встроена в Java 8 и более поздние версии. Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и SimpleDateFormat.
Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите множество примеров и пояснений в Stack Overflow. Спецификация: JSR 310.
Вы можете обмениваться объектами java.time непосредственно с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.
Проект ThreeTen-Extra расширяет java.time дополнительными классами. . Этот проект является испытательным полигоном для возможных дополнений к java.time в будущем. Здесь вы можете найти несколько полезных классов, таких как Interval a>, YearWeek, YearQuarter и подробнее.
Ответ 7 · jarnbjo
Количество миллисекунд в году выходит далеко за пределы диапазона int, поэтому как целочисленное приведение ten_year_later.getTimeInMillis() - expiration.getTimeInMillis(), так и вычисление 365 * 24 * 60 * 60 * 1000 будут оцениваться как неверные значения.
ten_year_later должно быть правильным. Нет необходимости вызывать calculateFields, как писал Р. Бемроуз.