Я новичок в программировании, поэтому это может быть глупый вопрос, но я не могу найти никакого решения. Я хочу рассчитать разницу (в днях) между датами. В большинстве случаев это работает, но когда меняется месяц, я получаю странные решения.
Первый пример:
today - 30 сентября 2018 = 78 дней,
today - 31 сентября 2018 = 79 дней (??),
today - 1 октября 2018 = 80 дней
Второй пример:
today - 31 августа 2018 = 49 дней,
today - 1 сентября 2018 = 49 дней
Код
private static int[] abstandTage(GregorianCalendar date1, ArrayList<GregorianCalendar> csvDate)
{
int[] abstand = new int[csvDate.size()];
int i = 0;
while ( i < csvDate.size() )
{
long diffInMillis = csvDate.get(i).getTimeInMillis() - date1.getTimeInMillis();
long tage = diffInMillis / 1000 / 60 / 60 / 24;
abstand[i] = (int) tage;
i++ ;
}
return abstand;
}
date1 - это предопределенная дата, csvDate - это список с датами. Кто-нибудь может мне помочь?
заранее спасибо Алекс
Я бы рекомендовал программировать против интерфейса, изменив подпись на int[] abstandTage(GregorianCalendar date1, List<GregorianCalendar> csvDate), подробнее об этом здесь.
Результаты неожиданные, согласен. С сегодняшнего дня (13 июля) по 30 сентября должно быть 79 дней. До 1 сентября должно быть 50 дней. Похоже, сентябрьские дни неправильные? Как вы создаете объекты GregorianCalendar? Не могли бы вы создать минимальный, полный и проверяемый пример, пожалуйста?
Возможный дубликат Разница в днях между двумя датами на Java?
Возможный почти дубликат Создание объекта даты Java из года, месяца, дня




Массив различий можно рассчитать с помощью ChronoUnit. Вы также можете использовать поток для дальнейшего упрощения вашей реализации:
private static int[] abstandTage(GregorianCalendar date1,
ArrayList<GregorianCalendar> csvDate) {
return csvDate.stream()
.mapToInt(csvdate -> (int)
ChronoUnit.DAYS.between(date1.toZonedDateTime(), csvdate.toZonedDateTime()))
.toArray();
}
Если мы не можем избежать класса GregorianCalendar, это правильный путь. Еще лучше, если бы вызывающий абонент передал LocalDate или другой современный класс даты и времени.
Это произойдет, если вы создадите свои объекты GregorianCalendar, например, new GregorianCalendar(2018, 7, 13) для 13 июля. GregorianCalendar использует странную нумерацию месяцев, поэтому вы не получите 13 июля.
Решение состоит в том, чтобы выбросить этот давно устаревший и плохо спроектированный класс и создать свои даты, используя, например, LocalDate.of(2018, 7, 13) или даже лучше, LocalDate.of(2018, Month.JULY, 13). Затем используйте ChronoUnit.DAYS.between для определения количества дней между датами.
Ссылка на сайт:Учебник Oracle: Дата и время объясняет, как использовать java.time, современный API даты и времени Java.
Благодаря вашему комментарию (странная нумерация) я нашел решение. Тем не менее, я собираюсь попробовать способ, который вы предложили здесь, с Chronounit. Спасибо за ваши старания! Очень признателен.
@ dribble290 Старые унаследованные классы даты и времени действительно представляют собой чертовски ужасный беспорядок. Sun, Oracle и JCP по какой-то причине согласились заменить их на java.time. Собственно, по причинам многие. Вы не пожалеете, что приняли java.time.
Как упоминалось выше, вам нужно будет использовать здесь LocalDate:
SimpleDateformat sdf = new SimpleDateFormat("yyyyMMdd");
Date date1 = sdf.parse("20180713);
Date date2 = sdf.parse("20180930");
LocalDate startDate =
date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate endDate =
date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
long days = ChronoUnit.DAYS.between(startDate, endDate);
return days;
Преобразование с григорианского на дату выполняется с помощью:
Date newDate = new Date(date1.getTime());
Спасибо за желание внести свой вклад. Да, для LocalDate´, but when you can use LocalDate` от java.time, не вижу никаких причин для использования старомодного Date или печально известного проблемного SimpleDateFormat. Используйте исключительно java.time. Тоже проще.
Как отмечает Оле В.В. прокомментировал, ужасно неприятные старые классы даты и времени, такие как java.util.Date и java.text.SimpleDateFormat, теперь являются наследие, вытесненными классами java.time, встроенными в Java 8 и более поздних версий. См. Руководство от Oracle. Не смешивайте устаревшие классы были полностью вытеснены java.time, поэтому нет необходимости когда-либо смешивать.
Лучше не использовать давно устаревший и плохо спроектированный класс
GregorianCalendarи лучше позволить библиотечному методу делать вычисления за вас. Например,ChronoUnit.DAYS.between(), передача двух экземпляровLocalDate. Эти классы находятся вjava.time, современный API даты и времени Java.