Wie finde ich die Anzahl der Jahre zwischen zwei Daten?
Lesezeit: 3 Minuten
Micha Hainline
Ich versuche, ein Alter in Jahren von einem bestimmten Datum an zu bestimmen. Kennt jemand einen sauberen Weg, dies in Android zu tun? Ich habe natürlich die Java-API zur Verfügung, aber die direkte Java-API ist ziemlich schwach, und ich hatte gehofft, dass Android etwas hat, das mir hilft.
BEARBEITEN: Die mehrfachen Empfehlungen zur Verwendung von Joda Time in Android beunruhigen mich ein wenig aufgrund von Android Java – Joda Date ist langsam und verwandte Bedenken. Außerdem ist es wahrscheinlich übertrieben, eine nicht mit der Plattform gelieferte Bibliothek für etwas dieser Größe zu verwenden.
Eine ähnliche Frage: stackoverflow.com/questions/1116123/…
– Jeha
26. Oktober 2011 um 17:23 Uhr
Sowohl das Erbe Date/Calendar Klassen und Joda-Zeit wurden durch die ersetzt java.time Klassen. Die meisten von den java.time Funktionalität ist in Java 6 & Java 7 zurückportiert ThreeTen-Backport Projekt. Weiter angepasst für frühere Android in der ThreeTenABP Projekt. Sehen Wie benutzt man ThreeTenABP….
– Basilikum Bourque
1. Oktober 2018 um 0:40 Uhr
sinuhepop
import java.util.Calendar;
import java.util.Locale;
import static java.util.Calendar.*;
import java.util.Date;
public static int getDiffYears(Date first, Date last) {
Calendar a = getCalendar(first);
Calendar b = getCalendar(last);
int diff = b.get(YEAR) - a.get(YEAR);
if (a.get(MONTH) > b.get(MONTH) ||
(a.get(MONTH) == b.get(MONTH) && a.get(DATE) > b.get(DATE))) {
diff--;
}
return diff;
}
public static Calendar getCalendar(Date date) {
Calendar cal = Calendar.getInstance(Locale.US);
cal.setTime(date);
return cal;
}
Notiz: Wie Ole VV bemerkte, funktioniert dies nicht mit Daten vor Christus, da der Kalender funktioniert.
Was sind die Konstanten MONTH, YEAR und DATE ??
– Chris Sim
16. Juli 2013 um 9:57 Uhr
@ChrisSim: Sie sind statische Importe von Calendar.MONTH und so weiter.
– sinuhepop
16. Juli 2013 um 10:54 Uhr
Ich denke, statt DATE sollte es DAY_OF_MONTH sein.
– jiahao
19. Mai 2014 um 10:37 Uhr
@jiahao: Sie sind Synonyme
– sinuhepop
19. Mai 2014 um 12:49 Uhr
.get(YEAR) und .get(MONTH) sind jetzt veraltet, glaube ich. Eventuell bearbeiten?
Die alten Date-Time-Klassen sind wirklich schlecht, so schlecht, dass sowohl Sun als auch Oracle zugestimmt haben, sie durch die java.time-Klassen zu ersetzen. Wenn Sie überhaupt nennenswerte Arbeit mit Datums-/Uhrzeitwerten leisten, lohnt es sich, Ihrem Projekt eine Bibliothek hinzuzufügen. Die Joda-Time-Bibliothek war sehr erfolgreich und empfehlenswert, befindet sich aber jetzt im Wartungsmodus. Das Team empfiehlt die Migration zu den java.time-Klassen.
Ein Großteil der java.time-Funktionalität wurde in Java 6 & 7 zurückportiert ThreeTen-Backport und weiter angepasst Android in ThreeTenABP (sehen Wie benutzt man…).
Weitere Informationen finden Sie unter Oracle-Tutorial. Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Spezifikation ist JSR310.
Sie dürfen umtauschen java.time Objekte direkt mit Ihrer Datenbank. Verwenden ein JDBC-Treiber gemäß JDBC 4.2 oder später. Keine Notwendigkeit für Saiten, keine Notwendigkeit für java.sql.* Klassen.
Ich habe Joda viel dieses letzte Projekt verwendet. Es ist wirklich übertrieben in Bezug auf die Einrichtung …
– StarWind0
26. September 2015 um 9:00 Uhr
Nur zur Ausführung: public int getYears(org.java.util.Date time) { org.joda.time.DateTime now = org.joda.time.DateTime.now(); org.joda.time.DateTime then = new org.joda.time.DateTime(time.getTime()); return org.joda.time.Years.yearsBetween(now, then).getYears(); }
– Nielsvh
6. Oktober 2015 um 16:05 Uhr
Ich kann anscheinend noch keinen Kommentar abgeben, aber ich denke, Sie können einfach den DAY_OF_YEAR zum Training verwenden, wenn Sie die Jahre um eins anpassen sollten (kopiert und modifiziert von der aktuell besten Antwort).
public static int getDiffYears(Date first, Date last) {
Calendar a = getCalendar(first);
Calendar b = getCalendar(last);
int diff = b.get(Calendar.YEAR) - a.get(Calendar.YEAR);
if (a.get(Calendar.DAY_OF_YEAR) > b.get(Calendar.DAY_OF_YEAR)) {
diff--;
}
return diff;
}
public static Calendar getCalendar(Date date) {
Calendar cal = Calendar.getInstance(Locale.US);
cal.setTime(date);
return cal;
}
In ähnlicher Weise könnten Sie wahrscheinlich einfach die ms-Darstellungen der Zeit unterscheiden und durch die Anzahl der ms in einem Jahr dividieren. Halten Sie einfach alles in Longs und das sollte die meiste Zeit gut genug sein (Schaltjahre, autsch), aber es hängt von Ihrer Anwendung für die Anzahl der Jahre ab und wie leistungsfähig diese Funktion sein muss, ob es diese Art von Hack wert wäre.
Ich weiß, Sie haben nach einer sauberen Lösung gefragt, aber hier sind einmal zwei schmutzige:
static void diffYears1()
{
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Calendar calendar1 = Calendar.getInstance(); // now
String toDate = dateFormat.format(calendar1.getTime());
Calendar calendar2 = Calendar.getInstance();
calendar2.add(Calendar.DAY_OF_YEAR, -7000); // some date in the past
String fromDate = dateFormat.format(calendar2.getTime());
// just simply add one year at a time to the earlier date until it becomes later then the other one
int years = 0;
while(true)
{
calendar2.add(Calendar.YEAR, 1);
if(calendar2.getTimeInMillis() < calendar1.getTimeInMillis())
years++;
else
break;
}
System.out.println(years + " years between " + fromDate + " and " + toDate);
}
static void diffYears2()
{
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Calendar calendar1 = Calendar.getInstance(); // now
String toDate = dateFormat.format(calendar1.getTime());
Calendar calendar2 = Calendar.getInstance();
calendar2.add(Calendar.DAY_OF_YEAR, -7000); // some date in the past
String fromDate = dateFormat.format(calendar2.getTime());
// first get the years difference from the dates themselves
int years = calendar1.get(Calendar.YEAR) - calendar2.get(Calendar.YEAR);
// now make the earlier date the same year as the later
calendar2.set(Calendar.YEAR, calendar1.get(Calendar.YEAR));
// and see if new date become later, if so then one year was not whole, so subtract 1
if(calendar2.getTimeInMillis() > calendar1.getTimeInMillis())
years--;
System.out.println(years + " years between " + fromDate + " and " + toDate);
}
Folgendes halte ich für eine bessere Methode:
public int getYearsBetweenDates(Date first, Date second) {
Calendar firstCal = GregorianCalendar.getInstance();
Calendar secondCal = GregorianCalendar.getInstance();
firstCal.setTime(first);
secondCal.setTime(second);
secondCal.add(Calendar.DAY_OF_YEAR, 1 - firstCal.get(Calendar.DAY_OF_YEAR));
return secondCal.get(Calendar.YEAR) - firstCal.get(Calendar.YEAR);
}
BEARBEITEN
Abgesehen von einem Fehler, den ich behoben habe, funktioniert diese Methode nicht gut mit Schaltjahren. Hier ist eine vollständige Testsuite. Ich denke, Sie sind besser dran, die akzeptierte Antwort zu verwenden.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
class YearsBetweenDates {
public static int getYearsBetweenDates(Date first, Date second) {
Calendar firstCal = GregorianCalendar.getInstance();
Calendar secondCal = GregorianCalendar.getInstance();
firstCal.setTime(first);
secondCal.setTime(second);
secondCal.add(Calendar.DAY_OF_YEAR, 1 - firstCal.get(Calendar.DAY_OF_YEAR));
return secondCal.get(Calendar.YEAR) - firstCal.get(Calendar.YEAR);
}
private static class TestCase {
public Calendar date1;
public Calendar date2;
public int expectedYearDiff;
public String comment;
public TestCase(Calendar date1, Calendar date2, int expectedYearDiff, String comment) {
this.date1 = date1;
this.date2 = date2;
this.expectedYearDiff = expectedYearDiff;
this.comment = comment;
}
}
private static TestCase[] tests = {
new TestCase(
new GregorianCalendar(2014, Calendar.JULY, 15),
new GregorianCalendar(2015, Calendar.JULY, 15),
1,
"exactly one year"),
new TestCase(
new GregorianCalendar(2014, Calendar.JULY, 15),
new GregorianCalendar(2017, Calendar.JULY, 14),
2,
"one day less than 3 years"),
new TestCase(
new GregorianCalendar(2015, Calendar.NOVEMBER, 3),
new GregorianCalendar(2017, Calendar.MAY, 3),
1,
"a year and a half"),
new TestCase(
new GregorianCalendar(2016, Calendar.JULY, 15),
new GregorianCalendar(2017, Calendar.JULY, 15),
1,
"leap years do not compare correctly"),
};
public static void main(String[] args) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
for (TestCase t : tests) {
int diff = getYearsBetweenDates(t.date1.getTime(), t.date2.getTime());
String result = diff == t.expectedYearDiff ? "PASS" : "FAIL";
System.out.println(t.comment + ": " +
df.format(t.date1.getTime()) + " -> " +
df.format(t.date2.getTime()) + " = " +
diff + ": " + result);
}
}
}
Bienenfutter
praktisch, wenn Sie Kalender, Gebietsschema oder externe Bibliothek nicht einschränken möchten:
private static SimpleDateFormat YYYYMMDD = new SimpleDateFormat("yyyyMMdd");
public static Integer toDate8d(Date date) {
String s;
synchronized (YYYYMMDD) { s = YYYYMMDD.format(date); } // SimpleDateFormat thread safety
return Integer.valueOf(s);
}
public static Integer yearDiff(Date pEarlier, Date pLater) {
return (toDate8d(pLater) - toDate8d(pEarlier)) / 10000;
}
Irgendein Vorteil gegenüber dem Einzeiler von Basil Bourque? Ich empfehle, sich von der Form fernzuhalten SImpleDateFormat, es ist ein notorischer Unruhestifter einer Klasse. Und die Umwandlung in ein int der Zahlenwert, wenn das keinen Sinn macht? Mag ich nicht.
– Ole VV
27. Mai 2021 um 17:52 Uhr
Der Vergleich mit Basil ist hauptsächlich die Lernkurve von java.time, denn nicht jeder hätte viel Zeit zum Lernen; SimpleDateFormat ist nur so konzipiert, dass es minimal ist und nicht für Multithreading, so dass viele Leute auf Probleme stoßen können, wenn sie sich dessen nicht bewusst sind. Dies kann leicht durch einen einfachen synchronisierten Block gelöst werden; Diese int-Lösung verschiebt die logische Berechnung von einer Teilbibliothek zu einer einfachen mathematischen Berechnung, die in der Tat nicht komplex ist. Dies ist der geringste Nutzen der Bibliothek, es muss nicht einmal die Kalenderklasse einbezogen werden. dies ist intuitiv und leicht verständlich.
– Bienenfutter
12. September 2021 um 12:23 Uhr
11749500cookie-checkWie finde ich die Anzahl der Jahre zwischen zwei Daten?yes
Eine ähnliche Frage: stackoverflow.com/questions/1116123/…
– Jeha
26. Oktober 2011 um 17:23 Uhr
Sowohl das Erbe
Date
/Calendar
Klassen und Joda-Zeit wurden durch die ersetzt java.time Klassen. Die meisten von den java.time Funktionalität ist in Java 6 & Java 7 zurückportiert ThreeTen-Backport Projekt. Weiter angepasst für frühere Android in der ThreeTenABP Projekt. Sehen Wie benutzt man ThreeTenABP….– Basilikum Bourque
1. Oktober 2018 um 0:40 Uhr