Ich muss die Anzahl der Tage zwischen zwei Daten ermitteln : einer stammt aus einem Bericht und einer ist das aktuelle Datum. Mein Ausschnitt:
int age=calculateDifference(agingDate, today);
Hier calculateDifference
ist eine private Methode agingDate
und today
sind Date
Objekte, nur zur Verdeutlichung. Ich habe zwei Artikel aus einem Java-Forum verfolgt, Thread 1 / Thread 2 .
Es funktioniert gut in einem eigenständigen Programm, obwohl ich einen ungewöhnlichen Wertunterschied erhalte, wenn ich dies in meine Logik einbeziehe, um aus dem Bericht zu lesen.
Warum passiert es und wie kann ich es beheben?
EDIT:
Ich erhalte eine größere Anzahl von Tagen als die tatsächliche Anzahl von Tagen.
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;
}
Hinweis :
Leider hat mir keine der Antworten geholfen, das Problem zu lösen. Ich habe dieses Problem mit Hilfe der Joda-Zeitbibliothek gelöst .
java.util.Date
,java.util.Calendar
undjava.text.SimpleDateFormat
sind jetzt Erbe , durch die verdrängte java.time Klassen. Siehe Tutorial von Oracle . Ebenso befindet sich das Joda-Time- Projekt jetzt im Wartungsmodus , wobei das Team die Migration zu den Klassen java.time empfiehlt.Antworten:
Ich würde vorschlagen, dass Sie die ausgezeichnete Joda Time- Bibliothek anstelle des fehlerhaften java.util.Date und Ihrer Freunde verwenden. Du könntest einfach schreiben
quelle
Ich könnte zu spät sein, um am Spiel teilzunehmen, aber was zum Teufel? :) :)
Denken Sie, dass dies ein Threading-Problem ist? Wie verwenden Sie zum Beispiel die Ausgabe dieser Methode? ODER
Können wir Ihren Code ändern, um etwas so Einfaches zu tun wie:
quelle
Das diff / (24 * usw.) berücksichtigt die Zeitzone nicht. Wenn Ihre Standardzeitzone eine Sommerzeit enthält, kann dies die Berechnung beeinträchtigen.
Dieser Link hat eine nette kleine Implementierung.
Hier ist die Quelle des obigen Links für den Fall, dass der Link ausfällt:
und
quelle
while
sollte sein.while (cursor.getTimeInMillis() <= endInstant);
Andernfalls erhalten Sie eine Endlosschleife, wenn Sie weniger als einen Tag unterwegs sind.java.time
Verwenden Sie in Java 8 und höher das java.time-Framework ( Tutorial ).
Duration
Die
Duration
Klasse repräsentiert eine Zeitspanne als Anzahl von Sekunden plus einem Bruchteil einer Sekunde. Es kann Tage, Stunden, Minuten und Sekunden zählen.ChronoUnit
Wenn Sie nur die Anzahl der Tage benötigen, können Sie alternativ die Aufzählung verwenden . Beachten Sie, dass die Berechnungsmethoden eher ein als zurückgeben .
ChronoUnit
long
int
quelle
Es hängt davon ab, was Sie als Unterschied definieren. Um zwei Daten um Mitternacht zu vergleichen, können Sie dies tun.
quelle
quelle
Lösung unter Verwendung der Differenz zwischen Millisekunden und korrekter Rundung für Sommerzeitdaten:
Ein Hinweis: Natürlich müssen die Daten in einer bestimmten Zeitzone liegen.
Der wichtige Code:
Wenn Sie keine Runde möchten, können Sie UTC-Daten verwenden.
quelle
Illustration des Problems: (Mein Code berechnet Delta in Wochen, aber das gleiche Problem gilt für Delta in Tagen.)
Hier ist eine sehr vernünftig aussehende Implementierung:
Aber dieser Test wird fehlschlagen:
Der Grund ist:
Aber jeder, der sich einen Kalender ansieht, würde zustimmen, dass die Antwort 2 ist.
quelle
Ich benutze diese Funktion:
meine Funktion:
quelle
Schauen Sie sich die getFragmentInDays- Methoden in dieser Apache Commons-Lang-Klasse an
DateUtils
.quelle
Basierend auf der Antwort von @ Mad_Troll habe ich diese Methode entwickelt.
Ich habe ungefähr 30 Testfälle dagegen ausgeführt, ist die einzige Methode, die Fragmente von Subtageszeit korrekt behandelt.
Beispiel: Wenn Sie jetzt und jetzt + 1 Millisekunde vergehen, ist dies immer noch der gleiche Tag. Tun
1-1-13 23:59:59.098
zu1-1-13 23:59:59.099
Renditen 0 Tage, richtig; Alle anderen hier veröffentlichten Methoden führen dies nicht korrekt aus.Es ist erwähnenswert, dass es egal ist, wie Sie sie eingeben. Wenn Ihr Enddatum vor Ihrem Startdatum liegt, zählt es rückwärts.
Sie können die
@NotNull
Anmerkungen entfernen . Diese werden von Intellij verwendet, um Code-Analysen im laufenden Betrieb durchzuführenquelle
Sie sagen, dass es "in einem eigenständigen Programm gut funktioniert", aber dass Sie "ungewöhnliche Differenzwerte" erhalten, wenn Sie "dies in meine Logik aufnehmen, um aus dem Bericht zu lesen". Dies deutet darauf hin, dass Ihr Bericht einige Werte enthält, für die er nicht ordnungsgemäß funktioniert, und dass Ihr eigenständiges Programm diese Werte nicht enthält. Anstelle eines eigenständigen Programms schlage ich einen Testfall vor. Schreiben Sie einen Testfall wie ein eigenständiges Programm, das aus der TestCase-Klasse von JUnit stammt. Jetzt können Sie ein ganz bestimmtes Beispiel ausführen und wissen, welchen Wert Sie erwarten (und ihn heute nicht für den Testwert angeben, da sich der heutige Wert im Laufe der Zeit ändert). Wenn Sie die Werte eingeben, die Sie im Standalone-Programm verwendet haben, werden Ihre Tests wahrscheinlich bestanden. Das ist großartig - Sie möchten, dass diese Fälle weiter funktionieren. Fügen Sie jetzt einen Wert aus Ihrem Bericht hinzu, der nicht funktioniert. nicht richtig arbeiten. Ihr neuer Test wird wahrscheinlich fehlschlagen. Finden Sie heraus, warum es fehlschlägt, beheben Sie es und werden Sie grün (alle Tests bestanden). Führen Sie Ihren Bericht aus. Sehen Sie, was noch kaputt ist. schreibe einen Test; lass es passieren. Bald werden Sie feststellen, dass Ihr Bericht funktioniert.
quelle
Hundert Codezeilen für diese Grundfunktion ???
Nur eine einfache Methode:
quelle
quelle
ThreeTen-Extra
Die Antwort von Vitalii Fedorenko ist richtig und beschreibt, wie diese Berechnung auf moderne Weise mit in Java 8 und höher integrierten Java.time- Klassen (
Duration
&ChronoUnit
) durchgeführt wird (und auf Java 6 & 7 und Android zurückportiert wird ).Days
Wenn Sie routinemäßig mehrere Tage in Ihrem Code verwenden, können Sie bloße Ganzzahlen durch die Verwendung einer Klasse ersetzen. Die
Days
Klasse befindet sich im ThreeTen-Extra- Projekt, einer Erweiterung von java.time und als Grundlage für mögliche zukünftige Ergänzungen von java.time. DieDays
Klasse bietet eine typsichere Möglichkeit, eine Anzahl von Tagen in Ihrer Anwendung darzustellen. Die Klasse enthält geeignete Konstanten fürZERO
undONE
.java.util.Date
Konvertieren Sie die alten veralteten Objekte in der Frage zunächst in modernejava.time.Instant
Objekte. Die alten Datums- / Uhrzeitklassen haben neu hinzugefügte Methoden, um die Konvertierung in java.time zu erleichtern, zjava.util.Date::toInstant
.Übergeben Sie beide
Instant
Objekte an die Factory-Methode fürorg.threeten.extra.Days
.In der aktuellen Implementierung (2016-06) ist dies ein Wrapper-Aufruf. Weitere Informationen finden
java.time.temporal.ChronoUnit.DAYS.between
Sie imChronoUnit
Klassendokument. Um es klar auszudrücken : Alle GroßbuchstabenDAYS
sind in der Aufzählung enthalten,ChronoUnit
während Initial-CapDays
eine Klasse von ThreeTen-Extra ist.Sie können diese
Days
Objekte um Ihren eigenen Code herum übergeben. Sie können durch Aufrufen zu einem String im Standardformat ISO 8601 serialisierentoString
. Dieses FormatPnD
verwendet aP
, um den Anfang zu markieren, undD
bedeutet "Tage" mit einer Anzahl von Tagen dazwischen. Sowohl die java.time-Klassen als auch ThreeTen-Extra verwenden diese Standardformate standardmäßig, wenn Zeichenfolgen generiert und analysiert werden, die Datums- und Uhrzeitwerte darstellen.quelle
Dieser Code berechnet Tage zwischen 2 Datumszeichenfolgen:
quelle
Wenn Sie nach einer Lösung suchen, die die richtige Anzahl oder Tage zwischen z. B.
11/30/2014 23:59
und12/01/2014 00:01
der folgenden Lösung mit Joda Time zurückgibt .Diese Implementierung wird
1
als Differenz in Tagen zurückgegeben. Die meisten der hier veröffentlichten Lösungen berechnen die Differenz in Millisekunden zwischen zwei Daten.0
Dies bedeutet, dass dies zurückgegeben wird, da zwischen diesen beiden Daten nur ein Unterschied von 2 Minuten besteht.quelle
Sie sollten die Joda-Zeitbibliothek verwenden, da Java Util Date manchmal falsche Werte zurückgibt.
Joda vs Java Util Date
Zum Beispiel Tage zwischen gestern (TT-MM-JJJJ, 12-07-2016) und dem ersten Tag des Jahres 1957 (TT-MM-JJJJ, 01-01-1957):
Daher rate ich Ihnen wirklich, die Joda Time-Bibliothek zu verwenden.
quelle
Ich habe es so gemacht. es ist einfach :)
quelle