Różnica w dniach między dwiema datami w Javie?


81

Muszę znaleźć liczbę dni między dwiema datami : jeden pochodzi z raportu, a drugi to data bieżąca. Mój fragment:

  int age=calculateDifference(agingDate, today);

Oto calculateDifferenceprywatna metoda agingDatei todaysą to Dateobiekty, tylko dla twojego wyjaśnienia. Śledziłem dwa artykuły z forum Java, wątek 1 / wątek 2 .

Działa dobrze w samodzielnym programie, chociaż kiedy włączam to do mojej logiki do czytania z raportu, otrzymuję niezwykłą różnicę w wartościach.

Dlaczego tak się dzieje i jak mogę to naprawić?

EDYTOWAĆ :

Otrzymuję większą liczbę dni w porównaniu z rzeczywistą liczbą dni.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}

Uwaga :

Niestety żadna z odpowiedzi nie pomogła mi rozwiązać problemu. Mam osiągnąć ten problem z pomocą Joda czasu bibliotece.


3
Co masz na myśli mówiąc o niezwykłych wartościach różnic? Czy mógłbyś wyrazić się bardziej dosadnie lub podać jakiś przykład?
Marcel Gheorghita,

1
Czy możesz wysłać kod do metody obliczania różnicy?
Eugene Ryzhikov

FYI, kłopotliwego starych klas date-time, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz spuścizny , wyparta przez java.time klas. Zobacz samouczek firmy Oracle . Podobnie projekt Joda-Time jest teraz w trybie konserwacji , a zespół doradza migrację do klas java.time.
Basil Bourque

Odpowiedzi:


149

Sugerowałbym, abyś skorzystał z doskonałej biblioteki Joda Time zamiast wadliwego java.util.Date i przyjaciół. Możesz po prostu napisać

import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;

Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th 
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34

3
joda-time.sourceforge.net/faq.html#datediff - miałem zamiar zasugerować to samo.
Nebril

2
jodaInstance = new DateTime (jdkDate); Informacje na temat konwersji między czasem joda a java.util.Date i przyjaciółmi można znaleźć na stronie joda-time.sourceforge.net/userguide.html#JDK_Interoperability
Adam Schmideg

2
@ven coder - myślę, że możesz opublikować to jako osobne pytanie dotyczące korzystania z czasu joda. Możesz również podać fragment kodu, który daje pozornie błędny wynik.
Adam Schmideg

2
@ven coder - zaktualizowałem przykładowy kod, działa u mnie. Widzę odpowiedź na to pytanie. Pokaż kod, który dla Ciebie nie działa, tutaj lub w osobnym pytaniu.
Adam Schmideg

1
FYI, projekt Joda-Time jest teraz w trybie konserwacji , a zespół doradza migrację do klas java.time . Zobacz samouczek firmy Oracle .
Basil Bourque

48

Mogę być za późno na dołączenie do gry, ale co do cholery? :)

Czy uważasz, że jest to problem z wątkami? Na przykład jak korzystasz z wyników tej metody? LUB

Czy możemy zmienić Twój kod, aby zrobić coś tak prostego, jak:

Calendar calendar1 = Calendar.getInstance();
    Calendar calendar2 = Calendar.getInstance();
    calendar1.set(<your earlier date>);
    calendar2.set(<your current date>);
    long milliseconds1 = calendar1.getTimeInMillis();
    long milliseconds2 = calendar2.getTimeInMillis();
    long diff = milliseconds2 - milliseconds1;
    long diffSeconds = diff / 1000;
    long diffMinutes = diff / (60 * 1000);
    long diffHours = diff / (60 * 60 * 1000);
    long diffDays = diff / (24 * 60 * 60 * 1000);
    System.out.println("\nThe Date Different Example");
    System.out.println("Time in milliseconds: " + diff
 + " milliseconds.");
    System.out.println("Time in seconds: " + diffSeconds
 + " seconds.");
    System.out.println("Time in minutes: " + diffMinutes 
+ " minutes.");
    System.out.println("Time in hours: " + diffHours 
+ " hours.");
    System.out.println("Time in days: " + diffDays 
+ " days.");
  }

18
Ten kod nie zwraca uwagi na czas letni, więc wynik różnicy w dniach może nie być poprawny.
Johanna,

@Johanna Chociaż jest już dość późno, czy możesz podać przykład, kiedy to się nie powiedzie. Próbowałem wiele, ale nie mogłem znaleźć żadnych zakresów dat, dla których to się nie powiedzie. Dziękuję Ci.
abhilash

4
Ten błąd występuje tylko wtedy, gdy znajdujesz się w strefie czasowej (Twojej lokalnej strefie czasowej), w której jest używany czas letni, na przykład czas środkowoeuropejski, Berlin, Paryż lub Amsterdam. Dzień rozpoczęcia i zakończenia czasu letniego nie ma 24 godzin, na przykład 30 marca 2014 miał tylko 23 godziny, a 26 października 2014 będzie miał 25 godzin. Jeśli wcześniejsza data przypada przed 30 marca 2:00, a późniejsza data przypada po 30 marca 3:00, wówczas obliczenie nie powiedzie się.
Johanna

23

Różnica / (24 * itd.) Nie bierze pod uwagę strefy czasowej, więc jeśli domyślna strefa czasowa zawiera czas letni, może to spowodować wyłączenie obliczeń.

Ten link ma ładną małą implementację.

Oto źródło powyższego linku na wypadek, gdyby link zszedł:

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  //assert: startDate must be before endDate  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  

i

/** Using Calendar - THE CORRECT (& Faster) WAY**/  
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
  //assert: startDate must be before endDate  
  int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;  
  long endInstant = endDate.getTimeInMillis();  
  int presumedDays = 
    (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);  
  Calendar cursor = (Calendar) startDate.clone();  
  cursor.add(Calendar.DAY_OF_YEAR, presumedDays);  
  long instant = cursor.getTimeInMillis();  
  if (instant == endInstant)  
    return presumedDays;

  final int step = instant < endInstant ? 1 : -1;  
  do {  
    cursor.add(Calendar.DAY_OF_MONTH, step);  
    presumedDays += step;  
  } while (cursor.getTimeInMillis() != endInstant);  
  return presumedDays;  
}

4
Druga metoda jest zła, ostateczna whilepowinna być. while (cursor.getTimeInMillis() <= endInstant); W przeciwnym razie otrzymasz nieskończoną pętlę, jeśli mniej niż jeden dzień.
Chris.Jenkins

Z komentarza w linku "Należy mieć świadomość, że podany algorytm może dać" jeden dzień więcej "niż się spodziewacie. Daje 1 jako liczbę dni między 2009-02-28 19:00:00 a 2009-02-28 19:00:01 ”.
Zyoo

16

java.time

W Javie 8 i nowszych wersjach użyj struktury java.time ( samouczek ).

Duration

DurationKlasa reprezentuje okres czasu jako liczbę sekund plus drugiego frakcyjnej. Może liczyć dni, godziny, minuty i sekundy.

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());

ChronoUnit

Jeśli potrzebujesz tylko liczby dni, możesz też użyć rozszerzenia ChronoUnit wyliczenia . Zwróć uwagę, że metody obliczeniowe zwracają longzamiast int.

long days = ChronoUnit.DAYS.between( then, now );

pamiętaj również o przekazaniu dat do ChronoUnit.DAYS. między w odpowiedniej kolejności, w przeciwnym razie zwróci -ve wynik
RRR_J

13
import java.util.Calendar;
import java.util.Date;

public class Main {
    public static long calculateDays(String startDate, String endDate)
    {
        Date sDate = new Date(startDate);
        Date eDate = new Date(endDate);
        Calendar cal3 = Calendar.getInstance();
        cal3.setTime(sDate);
        Calendar cal4 = Calendar.getInstance();
        cal4.setTime(eDate);
        return daysBetween(cal3, cal4);
    }

    public static void main(String[] args) {
        System.out.println(calculateDays("2012/03/31", "2012/06/17"));

    }

    /** Using Calendar - THE CORRECT WAY**/
    public static long daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        long daysBetween = 0;
        while (date.before(endDate)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }
}

1
Pętla nie jest dobrym pomysłem. A co z wydajnością, skoro istnieją prostsze opcje wykonania tego samego?
angelcervera,

1
Poprawa wydajności polegałaby na zwiększaniu o potęgę 2, a następnie, gdy warunek date.before (endDate) jest fałszywy, wróć do poprzedniej iteracji i zresetuj element przyrostowy do 1. To znaczy, jeśli jesteś miliard dni dalej, zrobiłby może 30 iteracji zamiast miliarda. Możesz również poprawić wydajność, zgadując, sprawdzając milisekundy, ale prawdopodobnie byłoby to mniej eleganckie.
Muhd

12

To zależy od tego, co zdefiniujesz jako różnicę. Aby porównać dwie daty o północy, możesz to zrobić.

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;

9
Ten kod nie zwraca uwagi na czas letni, więc wynik może nie być poprawny.
Johanna,

@Johanna To rozwiązanie działa z czasem letnim. Gdy runda jest stosowana po dzieleniu, różnica ta jest ignorowana i wynik jest prawidłowy.
angelcervera

1
@angelcervera W większości przypadków będzie to poprawne, ale jeśli jest blisko, dodatkowa godzina może sprawić, że dokładność będzie +/- 1 dzień wolna (tj. będzie zaokrąglać w niewłaściwy sposób).
Muhd

3
@Muhd Yes, masz rację. Trzecia linia musi mieć postać: długie dni = Math.round ((dzień2 - dzień1) / 86400000D); Bardzo ważne jest, aby dzielnik był podwójną wartością.
angelcervera

3
Przepraszam. Dziś rano zapomniałem podłączyć do mózgu mój pierwszy moduł matematyczny. Myślałem, że odjęcie ujemnego wyniku zniweczy obliczenia. Powinniśmy móc głosować przeciw komentarzom.
Snekse

9

Rozwiązanie wykorzystujące różnicę między czasem milisekund, z prawidłowym zaokrągleniem dat czasu letniego:

public static long daysDiff(Date from, Date to) {
    return daysDiff(from.getTime(), to.getTime());
}

public static long daysDiff(long from, long to) {
    return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}

Jedna uwaga: oczywiście daty muszą być w jakiejś strefie czasowej.

Ważny kod:

Math.round( (to - from) / 86400000D )

Jeśli nie chcesz, możesz użyć dat UTC,


1
@marcolopes Nie, zwraca 32. System.out.println (daysDiff (new Date (2014, 2, 1), new Date (2014, 3, 2))); Uważaj, bo stycznia jest zero
angelcervera

4

Ilustracja problemu: (mój kod oblicza deltę w tygodniach, ale ten sam problem dotyczy delty w dniach)

Oto bardzo rozsądnie wyglądająca realizacja:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

Ale ten test się nie powiedzie:

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

Powodem jest:

Poniedziałek 09 marca 00:00:00 EDT 2009 = 1236,571,200,000
Poniedziałek 23 lutego 00:00:00 EST 2009 = 1235,365,200,000
MillisPerWeek = 604,800,000
Tak więc
(Mar09 - Feb23) / MillisPerWeek =
1,206,000,000 / 604,800,000 = 1,994 ...

ale każdy, kto patrzy na kalendarz, zgodzi się, że odpowiedź to 2.


1
Zwróć uwagę na EDT i EST . Patrzysz na czas letni. 168 godzin tygodniowo (+1 za „zyskanie” godziny na wiosnę) * dwa tygodnie, dodając dodatkową godzinę czasu letniego i masz: 335/168 = 1,9940476190.
jpswain

3

Używam tej funkcji:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

moja funkcja:

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }


2

Opierając się na odpowiedzi @ Mad_Troll, opracowałem tę metodę.

Przeprowadziłem około 30 przypadków testowych przeciwko temu, jest to jedyna metoda, która poprawnie obsługuje fragmenty pory dnia.

Przykład: Jeśli zdasz teraz i teraz + 1 milisekunda, to nadal jest ten sam dzień. Robi 1-1-13 23:59:59.098się 1-1-13 23:59:59.099zwraca 0 dni, poprawnie; wiele innych opublikowanych tutaj metod nie zrobi tego poprawnie.

Warto zauważyć, że nie dba o to, w jaki sposób je umieścisz, jeśli data zakończenia przypada przed datą rozpoczęcia, będzie odliczana wstecz.

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

Możesz usunąć @NotNulladnotacje, są one używane przez Intellij do analizy kodu w locie


Uwzględniam Millisa, ten kalkulator nie, zakładam, że zaokrągla liczby do 0. Jak napisałem w górnej części odpowiedzi. Spłaszcz swoje godziny / minuty / sekundy / milis, a przekonasz się, że będą wtedy liczyć poprawnie.
Chris.Jenkins

1

Mówisz, że „działa dobrze w samodzielnym programie”, ale otrzymujesz „niezwykłe wartości różnic”, gdy „włączasz to do mojej logiki, aby odczytać z raportu”. To sugeruje, że raport zawiera wartości, dla których nie działa poprawnie, a Twój samodzielny program nie ma tych wartości. Zamiast samodzielnego programu proponuję przypadek testowy. Napisz przypadek testowy podobnie jak w przypadku samodzielnego programu, podklasując go z klasy TestCase firmy JUnit. Teraz możesz uruchomić bardzo konkretny przykład, wiedząc, jakiej wartości oczekujesz (i nie podawaj jej dzisiaj za wartość testową, ponieważ dziś zmienia się w czasie). Jeśli wpiszesz wartości, których użyłeś w samodzielnym programie, twoje testy prawdopodobnie przejdą. To świetnie - chcesz, aby te sprawy nadal działały. Teraz dodaj wartość ze swojego raportu, taką, która nie t działa dobrze. Twój nowy test prawdopodobnie się nie powiedzie. Dowiedz się, dlaczego to się nie udaje, napraw to i przejdź do koloru zielonego (wszystkie testy zakończą się pomyślnie). Uruchom raport. Zobacz, co jest nadal zepsute; napisać test; spraw, by minęło. Wkrótce przekonasz się, że Twój raport działa.


1

Sto wierszy kodu dla tej podstawowej funkcji ???

Tylko prosta metoda:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}

5
Ignoruje strefy czasowe. Ignoruje czas letni i inne anomalie. Ignoruje zaokrąglanie dni niepełnych.
Basil Bourque

1
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;
}

1

ThreeTen-Extra

Odpowiedz przez Vitalii Fedorenko jest poprawna, opisujący jak wykonać te obliczenia w nowoczesny sposób z java.time klas ( Durationi ChronoUnit) wbudowanych w Java 8 i później (i back-przeniesiony do Java 6 i 7 i Android ).

Days

Jeśli używasz rutynowo w swoim kodzie liczby dni, możesz zastąpić zwykłe liczby całkowite za pomocą klasy. DaysKlasy można znaleźć w ThreeTen-Extra projektu przedłużenia java.time i udowodnienia podstawy do ewentualnych uzupełnień java.time przyszłych. DaysKlasa dostarcza typu bezpieczny sposób reprezentujący liczbę dni w aplikacji. Klasa zawiera wygodne stałe dla ZEROi ONE.

Biorąc pod uwagę stare, przestarzałe java.util.Dateobiekty w pytaniu, najpierw przekonwertuj je na nowoczesne java.time.Instantobiekty. Stare klasy data-czas mają nowo dodane metody ułatwiające konwersję do java.time, takie jak java.util.Date::toInstant.

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Przekaż oba Instantobiekty do metody fabrycznej dla org.threeten.extra.Days.

W bieżącej implementacji (2016-06) jest to wywołanie opakowania java.time.temporal.ChronoUnit.DAYS.between, ChronoUnitszczegółowe informacje można znaleźć w dokumentacji klasy. Dla jasności: wszystkie wielkie litery DAYSsą w wyliczeniu, ChronoUnitpodczas gdy inicjał Daysjest klasą z ThreeTen-Extra.

Days days = Days.between( start , stop );

Możesz przekazać te Daysobiekty dookoła własnego kodu. Możesz serializować do ciągu w standardowym formacie ISO 8601 , wywołując toString. Ten format PnDużywa a Pdo zaznaczenia początku i Doznacza „dni”, z pewną liczbą dni pomiędzy nimi. Obie klasy java.time i ThreeTen-Extra używają tych standardowych formatów domyślnie podczas generowania i analizowania ciągów znaków reprezentujących wartości daty i godziny.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );  

0

Ten kod oblicza dni między dwoma ciągami dat:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}

0

Jeśli szukasz rozwiązania, które zwraca odpowiednią liczbę lub dni między np. 11/30/2014 23:59A 12/01/2014 00:01oto rozwiązanie wykorzystujące czas Joda.

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

Ta implementacja zwróci 1różnicę w dniach. Większość przedstawionych tutaj rozwiązań oblicza różnicę w milisekundach między dwiema datami. Oznacza to, 0że zostanie zwrócony, ponieważ różnica między tymi dwiema datami wynosi tylko 2 minuty.


0

Powinieneś używać biblioteki Joda Time, ponieważ Java Util Date czasami zwraca nieprawidłowe wartości.

Joda vs Java Util Date

Na przykład dni między wczoraj (dd-mm-rrrr, 12-07-2016) a pierwszym dniem roku 1957 (dd-mm-rrrr, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

Dlatego naprawdę radzę korzystać z biblioteki Joda Time.


1
FYI, chociaż Joda-Time jest nadal aktywnie wspierana, jego zespół programistów zaleca migrację do java.time . Cytując z ich strony głównej: „Joda-Time jest de facto standardową biblioteką daty i godziny dla Java przed wersją Java SE 8. Użytkownicy są teraz proszeni o migrację do java.time (JSR-310)”.
Basil Bourque,

-6

Zrobiłem to w ten sposób. To jest łatwe :)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;

4
Zrób trochę testów na tym, bardzo szybko zorientujesz się, że to nie zadziała. Czy od 31 grudnia 2013 r. Do 1 stycznia 2014 r. Jest to jedna różnica dnia, prawda? Twoje obliczenia wystarczą, 1 - 365 = -364. Co z pewnością nie jest poprawne.
Chris.Jenkins,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.