How can I find the number of years between two dates?

JavaAndroidDate

Java Problem Overview


I am trying to determine an age in years from a certain date. Does anyone know a clean way to do this in Android? I have the Java api available obviously, but the straight-up java api is pretty weak, and I was hoping that Android has something to help me out.

EDIT: The multiple recommendations to use Joda time in Android worries me a bit due to https://stackoverflow.com/questions/5059663/android-java-joda-date-is-slow and related concerns. Also, pulling in a library not shipped with the platform for something this size is probably overkill.

Java Solutions


Solution 1 - Java

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

Note: as Ole V.V. noticed, this won't work with dates before Christ due how Calendar works.

Solution 2 - Java

tl;dr

ChronoUnit.YEARS.between( 
    LocalDate.of( 2010 , 1 , 1 ) , 
    LocalDate.now( ZoneId.of( "America/Montreal" ) ) 
)

java.time

The old date-time classes really are bad, so bad that both Sun & Oracle agreed to supplant them with the java.time classes. If you do any significant work at all with date-time values, adding a library to your project is worthwhile. The Joda-Time library was highly successful and recommended, but is now in maintenance mode. The team advises migration to the java.time classes.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

LocalDate start = LocalDate.of( 2010 , 1 , 1 ) ;
LocalDate stop = LocalDate.now( ZoneId.of( "America/Montreal" ) );
long years = java.time.temporal.ChronoUnit.YEARS.between( start , stop );

Dump to console.

System.out.println( "start: " + start + " | stop: " + stop + " | years: " + years ) ;

>start: 2010-01-01 | stop: 2016-09-06 | years: 6


Table of all date-time types in Java, both modern and legacy


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Table of which java.time library to use with which version of Java or Android

Solution 3 - Java

I would recommend using the great Joda-Time library for everything date related in Java.

For your needs you can use the Years.yearsBetween() method.

Solution 4 - Java

I apparently can't comment yet, but I think you can just use the DAY_OF_YEAR to workout if you should adjust the years down one (copied and modified from current best answer)

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

Similarly you could probably just diff the ms representations of the time and divide by the number of ms in a year. Just keep everything in longs and that should be good enough most of the time (leap years, ouch) but it depends on your application for the number of years and how performant that function has to be weather it would be worth that kind of hack.

Solution 5 - Java

I know you have asked for a clean solution, but here are two dirty once:

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

Solution 6 - Java

Here's what I think is a better method:

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

EDIT

Apart from a bug which I fixed, this method does not work well with leap years. Here's a complete test suite. I guess you're better off using the accepted answer.

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

Solution 7 - Java

a handy one if you don't want to border Calendar, Locale, or external library:

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

Solution 8 - Java

If you don't want to calculate it using java's Calendar you can use Androids Time class It is supposed to be faster but I didn't notice much difference when i switched.

I could not find any pre-defined functions to determine time between 2 dates for an age in Android. There are some nice helper functions to get formatted time between dates in the DateUtils but that's probably not what you want.

Solution 9 - Java

// int year =2000;  int month =9 ;    int day=30;
  
    public int getAge (int year, int month, int day) {
            
            GregorianCalendar cal = new GregorianCalendar();
            int y, m, d, noofyears;         

            y = cal.get(Calendar.YEAR);// current year ,
            m = cal.get(Calendar.MONTH);// current month 
            d = cal.get(Calendar.DAY_OF_MONTH);//current day
            cal.set(year, month, day);// here ur date 
            noofyears = y - cal.get(Calendar.YEAR);
            if ((m < cal.get(Calendar.MONTH))
                            || ((m == cal.get(Calendar.MONTH)) && (d < cal
                                            .get(Calendar.DAY_OF_MONTH)))) {
                    --noofyears;
            }
            if(noofyears < 0)
                    throw new IllegalArgumentException("age < 0");
             System.out.println(noofyears);
            return noofyears;
    

Solution 10 - Java

This will work and if you want the number of years replace 12 to 1

    String date1 = "07-01-2015";
    String date2 = "07-11-2015";
    int i = Integer.parseInt(date1.substring(6));
    int j = Integer.parseInt(date2.substring(6));
    int p = Integer.parseInt(date1.substring(3,5));
    int q = Integer.parseInt(date2.substring(3,5));


    int z;
    if(q>=p){
        z=q-p + (j-i)*12;
    }else{
        z=p-q + (j-i)*12;
    }
    System.out.println("The Total Months difference between two dates is --> "+z+" Months");

Solution 11 - Java

Thanks @Ole V.v for reviewing it: i have found some inbuilt library classes which does the same

    int noOfMonths = 0;
	org.joda.time.format.DateTimeFormatter formatter = DateTimeFormat
			.forPattern("yyyy-MM-dd");
	DateTime dt = formatter.parseDateTime(startDate);

	DateTime endDate11 = new DateTime();
	Months m = Months.monthsBetween(dt, endDate11);
	noOfMonths = m.getMonths();
    System.out.println(noOfMonths);

Solution 12 - Java

Try this:

int getYear(Date date1,Date date2){ 
	  SimpleDateFormat simpleDateformat=new SimpleDateFormat("yyyy");
	  Integer.parseInt(simpleDateformat.format(date1));
	  
	  return Integer.parseInt(simpleDateformat.format(date2))- Integer.parseInt(simpleDateformat.format(date1));
		  
	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMicah HainlineView Question on Stackoverflow
Solution 1 - JavasinuhepopView Answer on Stackoverflow
Solution 2 - JavaBasil BourqueView Answer on Stackoverflow
Solution 3 - JavaMarceloView Answer on Stackoverflow
Solution 4 - JavasagechufiView Answer on Stackoverflow
Solution 5 - JavaMa99uSView Answer on Stackoverflow
Solution 6 - JavaSnakEView Answer on Stackoverflow
Solution 7 - JavaBee ChowView Answer on Stackoverflow
Solution 8 - JavadweeboView Answer on Stackoverflow
Solution 9 - JavaRishi GautamView Answer on Stackoverflow
Solution 10 - JavakeyRenView Answer on Stackoverflow
Solution 11 - JavakeyRenView Answer on Stackoverflow
Solution 12 - Javaabobjects.comView Answer on Stackoverflow