Рассчитать дни между двумя датами в Java 8


252

Я знаю, что на SO есть много вопросов о том, как его получить, но я хочу и пример использования нового Java 8 Date API. Я также знаю библиотеку JodaTime, но я хочу работать без внешних библиотек.

Функция должна пожаловаться на эти ограничения:

  1. Предотвратить ошибки из даты сохранения
  2. Входными данными являются два объекта Date (без времени я знаю localdatetime, но мне нужно делать с экземплярами даты)

2
Примерно так, например ?
MadProgrammer

@MadProgrammer Не совсем - Продолжительность не самая подходящая для этого ...
assylias

@assylias Ну, это лучше, чем то, что было у ОП
MadProgrammer

@assylias Тогда что это?
MadProgrammer

16
@MadProgrammer DAYS.between(localDate1, localDate2).
assylias

Ответы:


436

Если вы хотите логических календарных дней , используйте DAYS.between()метод из java.time.temporal.ChronoUnit:

LocalDate dateBefore;
LocalDate dateAfter;
long daysBetween = DAYS.between(dateBefore, dateAfter);

Если вы хотите буквальные 24-часовые дни ( продолжительность ), вы можете использовать Durationкласс вместо:

LocalDate today = LocalDate.now()
LocalDate yesterday = today.minusDays(1);
// Duration oneDay = Duration.between(today, yesterday); // throws an exception
Duration.between(today.atStartOfDay(), yesterday.atStartOfDay()).toDays() // another option

Для получения дополнительной информации обратитесь к этому документу .


15
Это вызывает исключение, потому что метод Duration.between требует временных объектов, способных поддерживать блок SECONDS . Вместо этого попробуйте Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
VGR

5
Вместо today.atTime(0, 0)тебя можно сделать today.atStartOfDay().
Eee

5
@REACHUS Возможно, -1 был немного грубоват, потому что код, который вы предлагаете, работает, но Duration предназначен для измерения «количества времени, основанного на времени». Существует встроенный способ измерения количества дней, который не требует преобразования даты в дату и время.
assylias

Лучший ответ для LocalDate's - ответ @Sunil B ниже:ChronoUnit.DAYS.between(firstDate, secondDate)
Lappro

@Lappro, почему это лучше? Он использует тот же метод, что и мой ответ
синтагма

130

На основе комментариев VGR вот что вы можете использовать:

ChronoUnit.DAYS.between(firstDate, secondDate)

38

Вы можете использовать until():

LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
LocalDate christmas = LocalDate.of(2014, Month.DECEMBER, 25);

System.out.println("Until christmas: " + independenceDay.until(christmas));
System.out.println("Until christmas (with crono): " + independenceDay.until(christmas, ChronoUnit.DAYS));

4
Гоча, с которой я только что столкнулся с первой версией, untilзаключается в том, что она возвращает объект Period . Это вернет количество лет / месяцев / дней между двумя датами, а не фактическое количество дней. И getDays () для Period возвращает только часть дней (без учета количества лет или месяцев), а не общее количество дней. Вторая версия работает точно так, как нужно, чтобы получить количество дней между двумя датами.
М. Джастин

Есть ли для этого полная альтернатива? Так как для этого нужен Android SDk 26 и выше
ralphgabb

12

Вы можете использовать DAYS.betweenотjava.time.temporal.ChronoUnit

например

import java.time.temporal.ChronoUnit;

public long getDaysCountBetweenDates(LocalDate dateBefore, LocalDate dateAfter) {
    return DAYS.between(dateBefore, dateAfter);
}

10

Если startDate и endDate являются экземпляром java.util.Date

Мы можем использовать метод Между () из перечисления ChronoUnit :

public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
    //..
}

ChronoUnit.DAYS считать дни, которые завершены 24 часа .

import java.time.temporal.ChronoUnit;

ChronoUnit.DAYS.between(startDate.toInstant(), endDate.toInstant());

//OR 

ChronoUnit.DAYS.between(Instant.ofEpochMilli(startDate.getTime()), Instant.ofEpochMilli(endDate.getTime()));

8

Используйте ДНИ в enum java.time.temporal.ChronoUnit . Ниже приведен пример кода:

Выходные данные: * Количество дней между датой начала: 2015-03-01 и датой окончания: 2016-03-03: ==> 368. ** Количество дней между датой начала: 2016-03-03 и датой окончания: 2015-03-01 is ==> -368 *

package com.bitiknow.date;

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

/**
 * 
 * @author pradeep
 *
 */
public class LocalDateTimeTry {
    public static void main(String[] args) {

        // Date in String format.
        String dateString = "2015-03-01";

        // Converting date to Java8 Local date
        LocalDate startDate = LocalDate.parse(dateString);
        LocalDate endtDate = LocalDate.now();
        // Range = End date - Start date
        Long range = ChronoUnit.DAYS.between(startDate, endtDate);
        System.out.println("Number of days between the start date : " + dateString + " and end date : " + endtDate
                + " is  ==> " + range);

        range = ChronoUnit.DAYS.between(endtDate, startDate);
        System.out.println("Number of days between the start date : " + endtDate + " and end date : " + dateString
                + " is  ==> " + range);

    }

}

8

Все говорят, что используют ChronoUnit.DAYS.between, но это просто делегирует другой метод, который вы можете вызвать сами. Так что вы также можете сделать firstDate.until(secondDate, ChronoUnit.DAYS).

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


FWIW ... Я не уверен, почему оба существуют. Бывают ли времена, когда один читается лучше, а другие? Когда / почему?
Nafg

5

Ну вот:

public class DemoDate {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("Current date: " + today);

        //add 1 month to the current date
        LocalDate date2 = today.plus(1, ChronoUnit.MONTHS);
        System.out.println("Next month: " + date2);

        // Put latest date 1st and old date 2nd in 'between' method to get -ve date difference
        long daysNegative = ChronoUnit.DAYS.between(date2, today);
        System.out.println("Days : "+daysNegative);

        // Put old date 1st and new date 2nd in 'between' method to get +ve date difference
        long datePositive = ChronoUnit.DAYS.between(today, date2);
        System.out.println("Days : "+datePositive);
    }
}

5

Получить количество дней до Рождества с текущего дня, попробуйте это

System.out.println(ChronoUnit.DAYS.between(LocalDate.now(),LocalDate.of(Year.now().getValue(), Month.DECEMBER, 25)));

3

Если цель состоит в том, чтобы просто получить разницу в днях, и поскольку вышеупомянутые ответы упоминают о методах делегатов, то хотелось бы указать, что однажды можно также просто использовать -

public long daysInBetween(java.time.LocalDate startDate, java.time.LocalDate endDate) {
  // Check for null values here

  return endDate.toEpochDay() - startDate.toEpochDay();
}

1
Попадание в ловушку позволяет использовать «Period.between (date1, date2) .getDays ()», не осознавая, что вы теряете месяцы и годы разницы.
MrSmith42

2

получить дни между двумя датами дата является экземпляром java.util.Date

public static long daysBetweenTwoDates(Date dateFrom, Date dateTo) {
            return DAYS.between(Instant.ofEpochMilli(dateFrom.getTime()), Instant.ofEpochMilli(dateTo.getTime()));
        }

1

Я знаю, что этот вопрос для Java 8, но с Java 9 вы можете использовать:

public static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
    return startDate.datesUntil(endDate)
      .collect(Collectors.toList());
}

0

Используйте класс или метод, который лучше всего соответствует вашим потребностям:

  • Продолжительность класса,
  • Период класс,
  • или метод ChronoUnit.between .

Длительность измеряет количество времени, используя значения на основе времени (секунды, наносекунды).

Период использует значения на основе даты (годы, месяцы, дни).

Метод ChronoUnit.between полезен, когда вы хотите измерить количество времени только в одной единице времени, например, днях или секундах.

https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.