Разница в днях отличается в разных местах - PullRequest
0 голосов
/ 08 мая 2019

Ниже дается 279 дней на локальном сервере, но на другом сервере - 278, почему это происходит?

String sDate = "10-11-2017";
String eDate = "16-08-2018";
Date startDate = new SimpleDateFormat(MsmConstants.DATE_FORMAT).parse(sDate);
Date endDate = new SimpleDateFormat(MsmConstants.DATE_FORMAT).parse(eDate);
long difference = startDate.getTime() - endDate.getTime();
return Math.abs(difference / (1000 * 60 * 60 * 24));

Ответы [ 3 ]

1 голос
/ 08 мая 2019

Вероятно, это происходит из-за какого-то округления в сочетании с разницей в часовых поясах.

Поскольку оба операнда слева и справа от вашего оператора / являются целочисленными типами, с этим вы теряете точностьоператор.

Если вы измените свое выражение на: (double) difference / (1000 * 60 * 60 * 24), вы заметите, что на самом деле результат: -278.9583333333333

Причина, по которой это не точные дни, связана с переходом на летнее и т. д.корректировки даты / времени.

Если на вашем ПК установлены разные региональные настройки с сервера, на которых нет одинакового перехода на летнее время, возможно, вы получили другое число, которое превысило 279.

Как примечание, Java 7 и более ранние API даты / времени были очень глючными.SimpleDateFormat не был даже потокобезопасным, и было много проблем с переходом на летнее время и в подобных ситуациях.Вы должны действительно перейти на Java 8. То, что вы делаете, просто станет: Duration.between(startDate, endDate), и вычисление будет выполнено для вас правильно.

String sDate = "10-11-2017";
String eDate = "16-08-2018";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDateTime startDate = LocalDate.parse(sDate, formatter).atTime(0, 0);
LocalDateTime endDate = LocalDate.parse(eDate, formatter).atTime(0, 0);

return Duration.between(startDate, endDate).toDays();

Вы увидите, что это действительно дает вам 279.

1 голос
/ 08 мая 2019

jbx уже в другой ответ объяснил, что пошло не так. 10 ноября зимой в северном полушарии, а 16 августа летом. Между этими двумя датами начинается летнее время (DST), из-за которого один день составляет всего 23 часа, поэтому рассчитанная вами разница составляет 1 час, а не 279 дней, которые вы ожидали и наблюдали локально.

java.time

Математика даты и времени слишком сложна и подвержена ошибкам, чтобы делать все так, как вы пытались. Вы должны всегда оставлять это хорошо проверенной библиотеке. Вот правильное и современное решение.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d-MM-uuuu");
    String sDate = "10-11-2017";
    String eDate = "16-08-2018";
    LocalDate startDate = LocalDate.parse(sDate, dateFormatter);
    LocalDate endDate = LocalDate.parse(eDate, dateFormatter);
    long difference = ChronoUnit.DAYS.between(startDate, endDate);
    System.out.println(Math.abs(difference));

Ожидаемый результат:

279

Поскольку строки даты не имеют времени суток, нет смысла использовать LocalDateTime. LocalDate - правильный класс для использования. Это также гарантирует, что никакое усечение не может произойти, поскольку между двумя датами всегда существует целое число дней.

Вопрос: будет ли это работать на Java 7?

Да, java.time требует как минимум Java 6 .

  • В Java 8 и более поздних версиях и на более новых устройствах Android (начиная с уровня API 26) встроен современный API.
  • В Java 6 и 7 получите ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. Ссылки внизу).
  • На (более старых) Android используется версия Android ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортируете классы даты и времени из org.threeten.bp с подпакетами.

Ссылки

0 голосов
/ 08 мая 2019

SimpleDataFormat использует часовой пояс JVM по умолчанию для создания Date объектов. В случае перехода на летнее время это может привести к разнице в +/- 1 день между двумя датами.

У вас есть несколько вариантов:

  1. Явно установите часовой пояс ваших SimpleDateFormat объектов на GMT / UTC.
  2. Явно установите часовой пояс вашей JVM на GMT / UTC.
  3. В Java 8 используйте новый java.time API; в более ранних версиях Java использовать альтернативу, такую ​​как Joda Time .
...