2013-10-19 6 views
23

Ich möchte den Unterschied zwischen zwei Calendar Objekte in Anzahl von Tagen finden, wenn es Datumsänderung wie Wenn Uhr von 23: 59-0: 00 tickte, sollte es einen Tagesunterschied geben.Wie bekomme ich die Anzahl der Tage zwischen zwei Kalender-Instanzen?

Ich schrieb dieses

public static int daysBetween(Calendar startDate, Calendar endDate) { 
    return Math.abs(startDate.get(Calendar.DAY_OF_MONTH)-endDate.get(Calendar.DAY_OF_MONTH)); 
} 

aber seine nicht funktioniert, da es dort nur Unterschied zwischen Tag gibt, wenn Monat Unterschied ist seine wertlos.

+1

Fragen wie das ist, warum sie joda Zeit schrieb. Java-Kalender ist so hoffnungslos ... Müssen Sie es verwenden? – iluxa

+5

Ursache, wenn Sie müssen, würde ich beide zu Millis konvertieren und mit diesen arbeiten, ehrlich gesagt :-) – iluxa

Antwort

23

folgende Vorgehensweise vor Versuchen:

public static long daysBetween(Calendar startDate, Calendar endDate) { 
    long end = endDate.getTimeInMillis(); 
    long start = startDate.getTimeInMillis(); 
    return TimeUnit.MILLISECONDS.toDays(Math.abs(end - start)); 
} 
+1

es könnte um 1 erhöhen. – CoDe

+11

Dies ist nicht die richtige Antwort für die ursprüngliche Frage. Diese Antwort ist korrekt, wenn der Unterschied eines Tages 86.400.000 Millisekunden (die Anzahl Millis in 24 Stunden) beträgt. Die ursprüngliche Frage lautete jedoch: "Wenn es eine Datumsänderung gibt, wie wenn die Uhr von 23: 59-0: 00 tickt, sollte es eine Tagesdifferenz geben". Die Frage definiert also einen 1-Tage-Unterschied, wenn der Kalendertag um 1 abweicht. – stackoverflowuser2010

6

Diese Funktion gibt die Anzahl der Tage zwischen zwei Kalender, wie die Anzahl der Kalendertage des Monats berechnet, die zwischen ihnen sind, das ist, was der OP wollte. Die Berechnung wird durchgeführt, indem gezählt wird, wie viele Vielfache von 86.400.000 Millisekunden zwischen den Kalendern liegen, nachdem beide auf Mitternacht ihrer jeweiligen Tage gesetzt wurden.

Zum Beispiel berechnet meine Funktion 1 Tag Differenz zwischen einem Kalender am 1. Januar, 23.59 Uhr und 2. Januar, 00.01 Uhr.

import java.util.concurrent.TimeUnit; 

/** 
* Compute the number of calendar days between two Calendar objects. 
* The desired value is the number of days of the month between the 
* two Calendars, not the number of milliseconds' worth of days. 
* @param startCal The earlier calendar 
* @param endCal The later calendar 
* @return the number of calendar days of the month between startCal and endCal 
*/ 
public static long calendarDaysBetween(Calendar startCal, Calendar endCal) { 

    // Create copies so we don't update the original calendars. 

    Calendar start = Calendar.getInstance(); 
    start.setTimeZone(startCal.getTimeZone()); 
    start.setTimeInMillis(startCal.getTimeInMillis()); 

    Calendar end = Calendar.getInstance(); 
    end.setTimeZone(endCal.getTimeZone()); 
    end.setTimeInMillis(endCal.getTimeInMillis()); 

    // Set the copies to be at midnight, but keep the day information. 

    start.set(Calendar.HOUR_OF_DAY, 0); 
    start.set(Calendar.MINUTE, 0); 
    start.set(Calendar.SECOND, 0); 
    start.set(Calendar.MILLISECOND, 0); 

    end.set(Calendar.HOUR_OF_DAY, 0); 
    end.set(Calendar.MINUTE, 0); 
    end.set(Calendar.SECOND, 0); 
    end.set(Calendar.MILLISECOND, 0); 

    // At this point, each calendar is set to midnight on 
    // their respective days. Now use TimeUnit.MILLISECONDS to 
    // compute the number of full days between the two of them. 

    return TimeUnit.MILLISECONDS.toDays(
      Math.abs(end.getTimeInMillis() - start.getTimeInMillis())); 
} 
-4

Kalender Tag1 = Calendar.getInstance();

Kalender Tag2 = Calendar.getInstance();

int diff = tag1.get (Kalender.DAY_OF_YEAR) - day2.get (Calendar.DAY_OF_YEAR);

+6

Dieser Code funktioniert nur, wenn beide Instanzen für dasselbe Jahr sind. –

2

UPDATE Das Joda-Time Projekt jetzt in maintenance mode berät Migration in die java.time Klassen. Siehe the Answer von Anees A für die Verwendung der ChronoUnit und anderer java.time-Klassen.

Joda-Time

Die alten java.util.Date/.Calendar Klassen notorisch sind lästig und sollte vermieden werden.

Verwenden Sie stattdessen die Bibliothek Joda-Time. Sofern Sie keine Java 8-Technologie haben, verwenden Sie in diesem Fall den integrierten java.time-Framework (nicht in Android ab 2015).

Da Sie sich nur für "Tage" interessieren, die als Daten definiert sind (nicht 24-Stunden-Perioden), konzentrieren wir uns auf Daten. Joda-Time bietet die Klasse LocalDate, um einen Nur-Datum-Wert ohne Uhrzeit oder Zeitzone darzustellen.

Wenn keine Zeitzone vorhanden ist, beachten Sie, dass die Zeitzone entscheidend bei der Bestimmung eines Datums wie "heute" ist. Ein neuer Tag dämmert früher nach Osten als nach Westen. Das Datum ist also nicht überall auf der Welt gleich, das Datum hängt von Ihrer Zeitzone ab.

DateTimeZone zone = DateTimeZone.forID ("America/Montreal"); 
LocalDate today = LocalDate.now (zone); 

Lassen Sie uns die Anzahl der Tage bis nächste Woche zählen, die natürlich sieben sein sollten.

LocalDate weekLater = today.plusWeeks (1); 
int elapsed = Days.daysBetween (today , weekLater).getDays(); 

Die getDays am Ende extrahiert eine ebene int Nummer von dem Objekt durch DaysdaysBetween zurückgegeben.

Dump zur Konsole.

System.out.println ("today: " + today + " to weekLater: " + weekLater + " is days: " + days); 

heute: 2015.12.22 bis weekLater: 2015.12.29 ist Tage: 7

Sie haben Kalender Objekte. Wir müssen sie in Joda-Time-Objekte umwandeln. Intern haben die Kalenderobjekte eine long Ganzzahl, die die Anzahl der Millisekunden seit der Epoche des ersten Moments von 1970 in UTC verfolgt. Wir können diese Nummer extrahieren und sie Joda-Time zuführen. Wir müssen auch die gewünschte Zeitzone angeben, mit der wir ein Datum bestimmen wollen.

long startMillis = myStartCalendar.getTimeInMillis(); 
DateTime startDateTime = new DateTime(startMillis , zone); 

long stopMillis = myStopCalendar.getTimeInMillis(); 
DateTime stopDateTime = new DateTime(stopMillis , zone); 

Konvertieren von DateTime-Objekten in LocalDate.

LocalDate start = startDateTime.toLocalDate(); 
LocalDate stop = stopDateTime.toLocalDate(); 

Jetzt machen Sie die gleiche verstrichene Berechnung, die wir vorher gesehen haben.

int elapsed = Days.daysBetween (start , stop).getDays(); 
10

In Java 8 und später, konnten wir einfach die java.time Klassen verwenden.

hoursBetween = ChronoUnit.HOURS.between(calendarObj.toInstant(), calendarObj.toInstant()); 

daysBetween = ChronoUnit.DAYS.between(calendarObj.toInstant(), calendarObj.toInstant()); 
+0

Kann auch vor Java 8 verwendet werden ... Ein großer Teil der java.time-Funktionalität wird im [*** ThreeTen-Backport ***] (http://www.threeten.org) auf einen Java 6 und Java 7 zurück portiert/threetenbp /) Projekt. Weiter angepasst für Android im [*** ThreeTenABP ***] (https://github.com/JakeWharton/ThreeTenABP) Projekt. –

0

Ich habe die ähnliche (nicht exakt gleiche) Vorgehensweise oben von https://stackoverflow.com/a/31800947/3845798.

Und haben Testfälle rund um die API geschrieben, für mich ist es gescheitert, wenn ich 8. März 2017 - als Startdatum und 8. April 2017 als Enddatum passiert.

Es gibt wenige Daten, an denen Sie den Unterschied nach 1 Tag sehen werden. Deshalb habe ich Art von ein paar kleine Änderungen an meinem api und meine aktuellen api sieht jetzt so etwas wie dieses Ich TimeUnit.MILLISECONDS.toDays bin nicht mit

public long getDays(long currentTime, long endDateTime) { 

Calendar endDateCalendar; 
Calendar currentDayCalendar; 


//expiration day 
endDateCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST")); 
endDateCalendar.setTimeInMillis(endDateTime); 
endDateCalendar.set(Calendar.MILLISECOND, 0); 
endDateCalendar.set(Calendar.MINUTE, 0); 
endDateCalendar.set(Calendar.HOUR, 0); 
endDateCalendar.set(Calendar.HOUR_OF_DAY, 0); 

//current day 
currentDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST")); 
currentDayCalendar.setTimeInMillis(currentTime); 
currentDayCalendar.set(Calendar.MILLISECOND, 0); 
currentDayCalendar.set(Calendar.MINUTE, 0); 
currentDayCalendar.set(Calendar.HOUR,0); 
currentDayCalendar.set(Calendar.HOUR_OF_DAY, 0); 


long remainingDays = (long)Math.ceil((float) (endDateCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis())/(24 * 60 * 60 * 1000)); 

return remainingDays;} 

gemacht, die mir einige Probleme verursacht wurden.

0

Erweiterung @ JK1 große Antwort:

public static long daysBetween(Calendar startDate, Calendar endDate) { 

    //Make sure we don't change the parameter passed 
    Calendar newStart = Calendar.getInstance(); 
    newStart.setTimeInMillis(startDate.); 
    newStart.set(Calendar.HOUR_OF_DAY, 0) 
    newStart.set(Calendar.MINUTE, 0) 
    newStart.set(Calendar.SECOND, 0) 
    newStart.set(Calendar.MILLISECOND, 0) 

    Calendar newEnd = Calendar.getInstance(); 
    newEnd.setTimeInMillis(startDate.); 
    newEnd.set(Calendar.HOUR_OF_DAY, 0) 
    newEnd.set(Calendar.MINUTE, 0) 
    newEnd.set(Calendar.SECOND, 0) 
    newEnd.set(Calendar.MILLISECOND, 0) 

    long end = newEnd.getTimeInMillis(); 
    long start = newStart.getTimeInMillis(); 
    return TimeUnit.MILLISECONDS.toDays(Math.abs(end - start)); 
} 
Verwandte Themen