Как уже говорили другие, избегайте класса GregorianCalendar
, если можете.У него есть некоторые проблемы с дизайном, и он уже давно устарел.
Однако ваша конкретная проблема была не в классе GregorianCalendar
.Он добавляет 97 дней в ваш код, принимая во внимание летнее время (DST) и все остальное.Как правильно отметили другие, добавление 97 дней к 4 декабря этого года дает вам 11 марта, день, когда летнее время только начинается в тех часовых поясах Северной Америки, где используется летнее время (месяц 11 в качестве аргумента конструктора, означающего декабрь, еще одна запутанная вещьоколо GregorianCalendar
).Поэтому последний добавленный день длился всего 23 часа.
Ваша настоящая проблема связана с комбинацией ChronoUnit.DAYS
и Instant
.Instant
является моментом времени без часового пояса и не имеет понятия дней.Вместо этого вы получите тот же результат, что и при подсчете часов, делении на 24 и отбрасывании остатка.Это редко полезно.А поскольку последний добавленный день составил всего 23 часа, он не учитывается.Вместо этого посчитайте дни между ZonedDateTime
или LocalDate
экземплярами или каким-либо другим классом java.time, в названии которого есть «date».Пример 1 (код Java, можете ли вы перевести себя?):
LocalDate start = LocalDate.of(2018, Month.DECEMBER, 4);
LocalDate laterB = start.plusDays(97);
System.out.println(ChronoUnit.DAYS.between(start, laterB));
Вывод:
97
Если вы не можете избежать получения GregorianCalendar
из устаревшего API, который вы не можете позволить себе сейчас обновить, первое, что вы должны сделать, - это преобразовать его, используя toZonedDateTime
, чтобы получить ZonedDateTime
.Это даст вам всю необходимую информацию от GregorianCalendar
, включая его часовой пояс и календарную дату.Другими словами, вы не должны использовать метод toInstant
, как вы это делали в коде вопроса.Пример 2:
GregorianCalendar start = new GregorianCalendar(2018, Calendar.DECEMBER, 4);
GregorianCalendar laterB = new GregorianCalendar(2018, Calendar.DECEMBER, 4);
laterB.add(Calendar.DATE, 97);
System.out.println(ChronoUnit.DAYS.between(start.toZonedDateTime(),
laterB.toZonedDateTime()));
Результат теперь тот, который вы ожидали:
97
Я запустил оба фрагмента с America / New_Yorkв качестве часового пояса по умолчанию.