Oblicz dni między dwiema datami w Javie 8

251

Wiem, że jest wiele pytań na temat SO, ale chcę i przykład przy użyciu nowego interfejsu API Java 8 Date. Znam również bibliotekę JodaTime, ale chcę sposób pracy bez bibliotek zewnętrznych.

Funkcja musi narzekać na te ograniczenia:

  1. Zapobiegaj błędom od daty oszczędzania
  2. Dane wejściowe to dwa obiekty Data (bez czasu znam lokalny czas, ale muszę zrobić z instancjami daty)
Marcos
źródło
2
Coś takiego na przykład ?
MadProgrammer,
@MadProgrammer Niezupełnie - Czas trwania nie jest najlepszy, aby to zrobić ...
assylias,
@assylias Cóż, to lepsze niż OP
MadProgrammer,
@assylias Więc co to jest?
MadProgrammer,
16
@MadProgrammer DAYS.between(localDate1, localDate2).
assylias,

Odpowiedzi:

435

Jeśli chcesz logiczne dni kalendarzowe , użyj DAYS.between()metody z java.time.temporal.ChronoUnit:

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

Jeśli chcesz dosłownie 24 godziny na dobę ( czas trwania ), możesz Durationzamiast tego skorzystać z zajęć:

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

Aby uzyskać więcej informacji, zapoznaj się z tym dokumentem .

syntagma
źródło
15
Zgłasza to wyjątek, ponieważ metoda Duration.between wymaga obiektów czasowych zdolnych do obsługi jednostki SECONDS . Zamiast tego spróbuj Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
VGR
5
Zamiast today.atTime(0, 0)ciebie możesz to zrobić today.atStartOfDay().
eee
5
@ REACHUS Być może -1 był nieco trudny, ponieważ proponowany przez ciebie kod działa, ale czas trwania ma mierzyć „ilość czasu zależną od czasu”. Istnieje wbudowany sposób pomiaru liczby dni, który nie wymaga konwersji z daty na datę i godzinę.
assylias,
Lepszą odpowiedzią na LocalDate jest odpowiedź @Sunila B poniżej:ChronoUnit.DAYS.between(firstDate, secondDate)
Lappro
@Lappro dlaczego jest lepiej? Używa tej samej metody, co moja odpowiedź
syntagma
130

Na podstawie komentarzy VGR tutaj możesz użyć:

ChronoUnit.DAYS.between(firstDate, secondDate)
Sunil B.
źródło
38

Możesz użyć 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));
nazar_art
źródło
4
Gotcha, którą właśnie spotkałem w pierwszej wersji, untilpolega na tym, że zwraca obiekt okresu . To zwróci liczbę lat / miesięcy / dni między dwiema datami, a nie faktyczną liczbę dni. A getDays () w okresie zwraca tylko część dni (nie biorąc pod uwagę liczby lat lub miesięcy), a nie całkowitą liczbę dni. Druga wersja działa dokładnie tak, jak trzeba, aby uzyskać liczbę dni między dwiema datami.
M. Justin,
Czy jest na to pełna alternatywa? Ponieważ wymaga Androida SDk 26 i nowszych
ralphgabb
12

Możesz używać DAYS.betweenzjava.time.temporal.ChronoUnit

na przykład

import java.time.temporal.ChronoUnit;

public long getDaysCountBetweenDates(LocalDate dateBefore, LocalDate dateAfter) {
    return DAYS.between(dateBefore, dateAfter);
}
Piotr Fryga
źródło
10

Jeśli startDate i endDate są instancją java.util.Date

Możemy użyć metody between () z ChronoUnit enum:

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

ChronoUnit.DAYS zlicza dni, które ukończyły 24 godziny .

import java.time.temporal.ChronoUnit;

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

//OR 

ChronoUnit.DAYS.between(Instant.ofEpochMilli(startDate.getTime()), Instant.ofEpochMilli(endDate.getTime()));
Pawan
źródło
8

Użyj DAYS in enum java.time.temporal.ChronoUnit . Poniżej znajduje się przykładowy kod:

Dane wyjściowe: * Liczba dni między datą rozpoczęcia: 01.03.2015 a datą zakończenia: 2016-03-03 wynosi ==> 368. ** Liczba dni między datą rozpoczęcia: 03.03.2016 i datą zakończenia: 01.03.2015 jest ==> -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);

    }

}
Pradeep Padmarajaiah
źródło
8

Wszyscy mówią, aby używać ChronoUnit.DAYS.between, ale to tylko deleguje na inną metodę, którą możesz nazwać sobą. Więc możesz też zrobić firstDate.until(secondDate, ChronoUnit.DAYS).

Dokumenty dla obu faktycznie wspominają o obu podejściach i mówią, aby użyć tego, który jest bardziej czytelny.

nafg
źródło
FWIW ... Nie jestem pewien, dlaczego oba istnieją. Czy są chwile, kiedy jeden jest bardziej czytelny, a czasami drugi? Kiedy, dlaczego?
nafg
5

Proszę bardzo:

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);
    }
}
Pra_A
źródło
5

Uzyskaj liczbę dni przed świętami Bożego Narodzenia od bieżącego dnia, spróbuj tego

System.out.println(ChronoUnit.DAYS.between(LocalDate.now(),LocalDate.of(Year.now().getValue(), Month.DECEMBER, 25)));
survivor_27
źródło
3

Jeśli celem jest uzyskanie różnicy w dniach, a ponieważ powyższe odpowiedzi wspominają o metodach delegowania, chcielibyśmy zauważyć, że kiedyś można po prostu użyć -

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

  return endDate.toEpochDay() - startDate.toEpochDay();
}
lewenshtein
źródło
1
Jesienią wpadnie w pułapkę, aby użyć „Period.between (date1, date2) .getDays ()”, nie zdając sobie sprawy, że tracisz miesiące i lata różnicy.
MrSmith42
2

get dni między dwiema datami data jest instancją java.util.Date

public static long daysBetweenTwoDates(Date dateFrom, Date dateTo) {
            return DAYS.between(Instant.ofEpochMilli(dateFrom.getTime()), Instant.ofEpochMilli(dateTo.getTime()));
        }
Mohamed.Abdo
źródło
1

Wiem, że to pytanie dotyczy Java 8, ale w Javie 9 możesz użyć:

public static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
    return startDate.datesUntil(endDate)
      .collect(Collectors.toList());
}
Xxtreem
źródło
0

Użyj klasy lub metody, która najlepiej odpowiada Twoim potrzebom:

  • klasa czasu trwania ,
  • Klasa okresowa ,
  • lub metoda ChronoUnit.between .

Czas trwania mierzy czas przy użyciu wartości opartych na czasie (sekundy, nanosekundy).

Okres używa wartości opartych na dacie (lata, miesiące, dni).

Metoda ChronoUnit.between jest przydatna, gdy chcesz zmierzyć ilość czasu w pojedynczej jednostce czasu, na przykład dni lub sekund.

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

Samuel
źródło