TimeUnit.DAYS.convert(
Math.abs(
new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("30-03-2020 00:00:00").getTime() -
new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("1-03-2020 00:00:00").getTime()
),
TimeUnit.MILLISECONDS)
Результат - 28, а должно быть 29. Может ли проблема заключаться в часовом поясе/местоположении?
Проблема в том, что из-за перехода на летнее время (в воскресенье, 8 марта 2020 года) между этими датами 28 дней и 23 часа. TimeUnit.DAYS.convert(...)
усекает результат до 28 дней.
Чтобы увидеть проблему (я нахожусь в восточном часовом поясе США):
SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
fmt.parse("1-03-2020 00:00:00").getTime();
System.out.println(diff);
System.out.println("Days: " + TimeUnit.DAYS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Hours: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Days: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS) / 24.0);
Вывод
``lang-none 2502000000 Дни: 28 Часы: 695 Дни: 28.95833333333333332
Для исправления используйте часовой пояс, в котором нет DST, например **UTC**:
SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); fmt.setTimeZone(TimeZone.getTimeZone("UTC")); long diff = fmt.parse("30-03-2020 00:00:00").getTime() - fmt.parse("1-03-2020 00:00:00").getTime();
*Вывод*
``lang-none
2505600000
Дни: 29
Часы: 696
Дни: 29.0
Причина этой проблемы уже упоминалась в Andreas'answer.
Вопрос в том, что именно вы хотите посчитать. Тот факт, что вы утверждаете, что фактическая разница должна быть 29, а не 28, и спрашиваете, может ли "местоположение/зональное время быть проблемой", показывает, что вы на самом деле хотите считать. Очевидно, вы хотите избавиться от любой разницы в часовых поясах.
Я предполагаю, что вы хотите вычислить только дни, без времени и часового пояса.
Ниже, в примере того, как можно правильно рассчитать количество дней между, я использую класс, который представляет именно это - дату без времени и часового пояса - LocalDate
.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MM-yyyy HH:mm:ss");
LocalDate start = LocalDate.parse("1-03-2020 00:00:00", formatter);
LocalDate end = LocalDate.parse("30-03-2020 00:00:00", formatter);
long daysBetween = ChronoUnit.DAYS.between(start, end);
Обратите внимание, что ChronoUnit
, DateTimeFormatter
и LocalDate
требуют как минимум Java 8, которая вам недоступна, согласно тегу [tag:java-7]. Однако, возможно, она будет доступна будущим читателям.
Как упоминал Ole V.V., существует также ThreeTen Backport, который переносит функциональность Java 8 Date and Time API на Java 6 и 7.