Количество дней между двумя датами в Joda-Time

Как найти разницу в днях между двумя Joda-Time DateTime экземпляры? С "разницей в днях" я имею в виду, что если начало в понедельник, а конец во вторник, я ожидаю возвращаемое значение 1 независимо от часа/минуты/секунды дат начала и окончания.

Days.daysBetween(start, end).getDays() дает мне 0, если начало вечера и заканчивается утром.

У меня также такая же проблема с другими полями даты, поэтому я надеялся, что будет общий способ "игнорировать" поля с меньшим значением.

Иными словами, месяцы между февралем и 4 марта также будут равны 1, как и часы между 14:45 и 15:12. Однако часовая разница между 14:01 и 14:55 будет равна 0.

Ответ 1

Досадно, ответ withTimeAtStartOfDay ошибочен, но только изредка. Вы хотите:

Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()

Оказывается, что "полночь/начало дня" иногда означает 1 утра (в некоторых местах это происходит в летнее время), которые Days.daysBetween не обрабатывают должным образом.

// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
                               end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
                               end.toLocalDate()).getDays());
// prints 1

Переход через LocalDate обходит всю проблему.

Ответ 2

Days Класс

Используя класс Days с withTimeAtStartOfDay должен работать:

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

Ответ 3

вы можете использовать LocalDate:

Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

Ответ 4

ТЛ; др

java.time.temporal.ChronoUnit.DAYS.between( 
    earlier.toLocalDate(), 
    later.toLocalDate() 
)

... или...

java.time.temporal.ChronoUnit.HOURS.between( 
    earlier.truncatedTo( ChronoUnit.HOURS )  , 
    later.truncatedTo( ChronoUnit.HOURS ) 
)

java.time

К вашему сведению, проект Joda-Time в настоящее время находится в режиме обслуживания, а команда рекомендует перейти на классы java.time.

Эквивалентом Joda-Time DateTime является ZonedDateTime.

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

Очевидно, вы хотите посчитать дни по датам, то есть вы хотите игнорировать время суток. Например, начиная с минуты до полуночи и заканчивая минутой после полуночи, вы получите один день. Для этого поведения извлеките LocalDate из вашего ZonedDateTime. Класс LocalDate представляет значение только для даты без времени суток и часового пояса.

LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;

Используйте ChronoUnit перечисление, чтобы вычислить прошедшие дни или другие единицы.

long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;

Округление

Что касается того, что вы спрашиваете о более общем способе подсчета, когда вас интересует разница часов в часах, а не полных часов в промежутке времени в шестьдесят минут, используйте метод truncatedTo.

Вот ваш пример с 14:45 до 15:12 в тот же день.

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );

long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );

1

Это не работает в течение нескольких дней. В этом случае используйте toLocalDate().


О java.time

Среда java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time, который теперь находится в режиме обслуживания, рекомендует выполнить переход на классы java.time.

Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите в Кару множество примеров и объяснений. Спецификация: JSR 310.

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в классах java.sql.*.

Где взять классы java.time?

  • Java SE 8, Java SE 9, Java SE 10 и более поздние версии
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые мелкие функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 & 7 в ThreeTen-Backport.
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранних версий Android (& lt; 26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянуто выше). Смотрите Как использовать ThreeTenABP....

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и еще more.

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и еще more.

Ответ 5

В принятом ответе строятся два объекта LocalDate, которые довольно дороги, если вы читаете много данных. Я использую это:

  public static int getDaysBetween(DateTime earlier, DateTime later)
  {
    return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
  }

Вызывая getMillis(), вы используете уже существующие переменные.
MILLISECONDS.toDays(), то, используя простой арифметический расчет, не создает никакого объекта.

Ответ 6

java.time.Period

Используйте класс java.time.Period для подсчета дней.

Поскольку вычисление разницы в Java 8 более интуитивно понятно с использованием LocalDate, LocalDateTime для представления двух дат

    LocalDate now = LocalDate.now();
    LocalDate inputDate = LocalDate.of(2018, 11, 28);

    Period period = Period.between( inputDate, now);
    int diff = period.getDays();
    System.out.println("diff = " + diff);

Ответ 7

DateTime  dt  = new DateTime(laterDate);        

DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());

System.out.println("No of days : " + newDate.getDayOfYear() - 1 );    

Ответ 8

public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}