Получение дней между текущей датой и другой датой в Java

Мне нужен метод, который возвращает разницу в днях между текущим днем ​​и любой другой датой, у меня есть следующее:

private long getDays(Date dateOp) {
    Calendar feCurrent=Calendar.getInstance();
    feCurrent.set(Calendar.HOUR_OF_DAY, 0);
    feCurrent.set(Calendar.MINUTE, 0);
    feCurrent.set(Calendar.SECOND, 0);

    Calendar feAna=Calendar.getInstance();
    feAna.setTime(dateOp);
    feAna.set(Calendar.HOUR_OF_DAY, 0);
    feAna.set(Calendar.MINUTE, 0);
    feAna.set(Calendar.SECOND, 0);
    feAna.getTime());
    long timeDiff = Math.abs(feAna.getTime().getTime() - feCurrent.getTime().getTime());

    return TimeUnit.MILLISECONDS.toDays(timeDiff);
}

Дело в том, что я всегда получаю на один день меньше, например, если дата в качестве параметра - 16 октября 2017 года, результат будет 3, но на самом деле их четыре, я отлаживал, и timeDiff для этих дат составляет 345599395, при преобразовании в дни составляет 3,999 ....

Кто-нибудь знает, почему не работает.

Кстати, дата в качестве параметра загружается из базы данных, потому что, если я попробовал с основным параметром, обе даты работают.


person zepol    schedule 12.10.2017    source источник
comment
Попробуйте также установить миллисекунды на 0 для обоих экземпляров календаря. cal.set(Calendar.MILLISECOND, 0)   -  person Titus    schedule 12.10.2017
comment
Кроме того, этот общий метод не сработает, если летнее время начнется между двумя датами, потому что будет день с 23 часами, что нарушает разделение.   -  person Dawood ibn Kareem    schedule 12.10.2017
comment
Обратите внимание, что классы Calendar и Date, которые являются частью старого API дат, теперь унаследованы. Вместо этого используйте классы нового API внутри пакета java.time.   -  person Zabuzard    schedule 12.10.2017
comment
Спасибо, я поставил миллисекунды, и это сработало, у меня не будет проблем с переходом на летнее время, потому что моя страна их не использует   -  person zepol    schedule 12.10.2017
comment
@Alex Если в вашей стране сейчас нет перехода на летнее время, это не значит, что его никогда не будет. Переход на летнее время определяется правительствами и законами, и вы не можете гарантировать, что никто не изменит это в будущем. В любом случае, если вы просто заботитесь о датах без учета времени дня или каких-либо эффектов DST, решение Szymon с LocalDate работает нормально. Но если вы хотите учитывать время дня и летнее время, в возможном дубликате, который я связал, есть множество вариантов - особенно this с ZonedDateTime   -  person    schedule 13.10.2017


Ответы (1)


Вы можете использовать java.time компоненты, если используете Java 8

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

final class PeriodTest {

    public static void main(String[] args) {
        LocalDate now = LocalDate.of(2017, 4, 4); // 2017-04-04
        LocalDate otherDate = LocalDate.of(2015, 10, 23); // 23-10-2015
        long days = Math.abs(ChronoUnit.DAYS.between(otherDate, now));

        System.out.println("Days = " + days);
    }
}

Вывод

Days = 529

Плюсы:

  • тебе не нужно играть со старым Calendar объектом
  • вы можете преобразовать java.util.Date в java.time.Instant с помощью метода Date.toInstant(), чтобы он работал с текущим примером

Решение Java 6

Для Java 6 вы можете использовать Joda-Time, который был предшественником Java 8 Time API.

import org.joda.time.Days;
import org.joda.time.LocalDate;

final class PeriodTest {

    public static void main(String[] args) {
        LocalDate now = LocalDate.parse("2017-04-04");
        LocalDate otherDate = LocalDate.parse("2015-10-23");

        int days = Math.abs(Days.daysBetween(now, otherDate).getDays());

        System.out.println("Days = " + days);
    }
}
person Szymon Stepniak    schedule 12.10.2017
comment
дата как параметр загружается из базы данных - person ; 12.10.2017
comment
@Arkadiy java.util.Date можно легко преобразовать в java.time.Instant методом Date.toInstant(). - person Szymon Stepniak; 12.10.2017
comment
Не могли бы вы тогда показать код, который будет использоваться для даты, представленной объектом Date? OP: если я попробовал с основными настройками, обе даты работают - person ; 12.10.2017
comment
Большое вам спасибо, я использовал это раньше, но, к сожалению, это приложение работает с Java 6, и оно ограничено внешними библиотеками, поэтому я могу работать только с - person zepol; 12.10.2017
comment
@Arkadiy Добавил пример с использованием java.util.Date - person Szymon Stepniak; 12.10.2017
comment
@Alex Тогда можешь использовать Joda-Time. Он работает с Java 6 и был предшественником Java 8 Time API. - person Szymon Stepniak; 12.10.2017
comment
@Alex Я добавил пример с использованием Joda-Time и без Java 8 Time API - person Szymon Stepniak; 12.10.2017
comment
Ваше редактирование нарушило это. Когда у вас было LocalDateTime, это было правильно, и переход на летнее время осуществлялся правильно. Когда вы изменили его на Date, вы неправильно сделали переход на летнее время. Я снял свой голос - person Dawood ibn Kareem; 12.10.2017
comment
@DawoodibnKareem Спасибо за комментарий, я этого не знаю. Единственная проблема в том, что Алекс все равно не может использовать решение Java 8: / - person Szymon Stepniak; 12.10.2017
comment
Конечно, но я думаю о людях, которые столкнутся с этим вопросом в будущем, а не только об Алексе. Оба ваших решения в настоящее время неверны. Если вы предлагаете решение для Java 8, я рекомендую сделать его полностью решением для Java 8, включая использование LocalDate. Я не знаю, как это сделать в joda-time, но полагаю, что в нем должно быть что-то похожее на LocalDate, которое вы можете использовать. - person Dawood ibn Kareem; 12.10.2017
comment
@DawoodibnKareem Ты прав. Я вернул пример кода к LocalDate, то же самое с Joda-Time. Алекс также может попробовать заменить java.util.Date на Joda-Time, чтобы избежать многих проблем. - person Szymon Stepniak; 12.10.2017
comment
Прохладный. Я вернул вам свой голос. - person Dawood ibn Kareem; 12.10.2017
comment
Для Java 6 и 7 вы можете использовать Threeten backport, отличный резервный порт для нового API даты и времени Java 8. Joda-Time находится в режиме обслуживания, и даже на их сайте есть предупреждение: Примечание. что Joda-Time считается в значительной степени завершенным проектом. Никаких серьезных улучшений не планируется. Если вы используете Java SE 8, перейдите на java.time (JSR-310). Так что для новых проектов лучше использовать бэкпорт. - person ; 13.10.2017