2

I have two dates (01/01/2012, 31/07/2014).

Would you please help me to calculate month difference between this two dates. If difference is 8 months 1 days i need result 9 months.

John
  • 56
  • 1
  • 1
  • 6
  • 3
    If you're using Java 8, use the new Time API, `Months.monthsBetween`, otherwise use JodaTime – MadProgrammer Nov 28 '14 at 03:03
  • possible duplicate of [Java Date month difference](http://stackoverflow.com/questions/1086396/java-date-month-difference) – Matt Coubrough Nov 28 '14 at 03:04
  • 4
    @MattCoubrough While JodaTime is mentioned, the prevailing answers are just bad ideas, you should never try and use basic arithmetic when trying to calculate differences in time, there is just too much variation and obscure rules which just make it guess work at best... – MadProgrammer Nov 28 '14 at 03:06
  • 3
    @MadProgrammer What I think we don't need is YET ANOTHER Date question, which can have MORE bad answers adding to the confusion over what the right approach is. If people had marked all the Date questions as dupes we might be approaching a single canonical answer. This is a dupe even if the previous questions' answers weren't great. Where is the research effort shown by the poster? – Matt Coubrough Nov 28 '14 at 03:11
  • @MattCoubrough No argument there, find one that actually answers the question correctly :) (the inclusion of the Time API into Java 8 has made many of the old questions out-of-date) – MadProgrammer Nov 28 '14 at 03:14
  • 2
    @MadProgrammer If the java.time package does indeed make old answers out-of-date, then new answers should be posted to those old questions. That is no excuse for a stream of repetive questions that are quickly polluting StackOverflow. – Basil Bourque Nov 28 '14 at 03:18
  • 1
    @BasilBourque The problem is, the prevailing accept or highly voted answers flood out any new content. I've seen this when trying to find answers for Objective C questions, which further increases the confusion to developers with little experience with the API or programming. Granted, this is a poor example of a question... – MadProgrammer Nov 28 '14 at 03:32

4 Answers4

10
Working Code:

public int monthsBetweenDates(Date startDate, Date endDate){

        Calendar start = Calendar.getInstance();
        start.setTime(startDate);

        Calendar end = Calendar.getInstance();
        end.setTime(endDate);

          int monthsBetween = 0;
            int dateDiff = end.get(Calendar.DAY_OF_MONTH)-start.get(Calendar.DAY_OF_MONTH);      

if(dateDiff<0) {
                int borrrow = end.getActualMaximum(Calendar.DAY_OF_MONTH);           
                 dateDiff = (end.get(Calendar.DAY_OF_MONTH)+borrrow)-start.get(Calendar.DAY_OF_MONTH);
                 monthsBetween--;

if(dateDiff>0) {
                     monthsBetween++;
                 }
            }
            else {
                monthsBetween++;
            }      
            monthsBetween += end.get(Calendar.MONTH)-start.get(Calendar.MONTH);      
            monthsBetween  += (end.get(Calendar.YEAR)-start.get(Calendar.YEAR))*12;      
            return monthsBetween;
     }
Md. Kamruzzaman
  • 1,895
  • 16
  • 26
  • 1
    If the dateDiff is 0 and the selection is a consecutive month you'll get two moths instead of 1. Don't think you need the else there. – TalMihr Feb 27 '17 at 09:39
  • This peace of code is not working for start date : 07 Feb 2017 and end date : 02 Mar 2017, please suggest me some solution. – Shubham Chauhan Mar 21 '17 at 14:43
  • @Talhihr This code return ceilling. If you pass same date as startDate and endDate It will return 1 month. If the dateDiff is 0 and the selection is a consecutive month you'll get two moths instead of 1 because that is 1 month 1 day. – Md. Kamruzzaman Mar 23 '17 at 06:40
  • 1
    @Shubham Chauhan In your case the differance is 24 days so this method will return 1, – Md. Kamruzzaman Mar 23 '17 at 06:47
  • @Md.Kamruzzaman Yes thanks for giving attention to my question i just found a solution i set date 01 Feb 2017 (instead of 07 Feb 2017) and 02 Mar 2017 and got my expected solution as 2 months. – Shubham Chauhan Mar 23 '17 at 06:52
9

You might use a Calendar like,

static int monthsBetween(Date a, Date b) {
    Calendar cal = Calendar.getInstance();
    if (a.before(b)) {
        cal.setTime(a);
    } else {
        cal.setTime(b);
        b = a;
    }
    int c = 0;
    while (cal.getTime().before(b)) {
        cal.add(Calendar.MONTH, 1);
        c++;
    }
    return c - 1;
}

then you could call it like

public static void main(String[] args) {
    String start = "01/01/2012";
    String end = "31/07/2014";
    DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    try {
        System.out.println(monthsBetween(sdf.parse(start), sdf.parse(end)));
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

Output is

30

Or, using Joda-Time

String start = "01/01/2012";
String end = "31/07/2014";
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
try {
    LocalDate a = LocalDate.fromDateFields(sdf.parse(start));
    LocalDate b = LocalDate.fromDateFields(sdf.parse(end));
    Period p = new Period(a, b);
    System.out.println((p.getYears() * 12) + p.getMonths());
} catch (ParseException e) {
    e.printStackTrace();
}

Output is also

30

Edit

Finally (as suggested in the comments), if you're using Java 8 you might use the new java.time classes like

String start = "01/01/2012";
String end = "31/07/2014";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate from = LocalDate.parse(start, formatter);
LocalDate to = LocalDate.parse(end, formatter);
System.out.println(from.until(to, ChronoUnit.MONTHS));

Output is (still)

30
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Please add `LocalDate from = LocalDate.of(2012, 01, 01);`, `LocalDate to = LocalDate.of(2014, 07, 31);`, `System.out.println(from.until(to, ChronoUnit.MONTHS));` for Java 8 then it will cover ALL the basics :P – MadProgrammer Nov 28 '14 at 03:25
  • 1
    @john That's the number of months until 8/1/2014; 24 months from 01/01/2012 to 01/01/2014 then 6 months until July for a total of 30 months (and 30 days). – Elliott Frisch Nov 28 '14 at 03:28
  • @MadProgrammer Edited, used `DateTimeFormatter` to be consistent with the other answers. – Elliott Frisch Nov 28 '14 at 03:35
  • Still a superior answer to the accepted answer without it, but thanks, now it's a complete answer :D – MadProgrammer Nov 28 '14 at 03:36
  • @ElliottFrisch thanks you. but need to count july. jan-july is 7 months instant of 6. – John Nov 28 '14 at 03:37
1
int months = 12*(toYear-fromYear)+(toMonth-fromMonth)+(toDay>=fromDay?1:0)

Where to is the later date and from is prior date

  • 2
    While this answer is probably valid for `kotlin` the original question was about `java`. Hence answers should be given within the language under analyses, otherwise they are off-topic. – bad_coder Jan 05 '20 at 14:32
  • Very powerful and shortest answer here. Good Luck! – AI Shakil Oct 18 '22 at 02:23
0

My code:

int getMonthCountBetween(Calendar cal1, Calendar cal2) {

        if(cal1.compareTo(cal2)>0) {
            Calendar cal=cal1;
            cal1=cal2;
            cal2=cal;
        }

        int months=0;

        int y1 = cal1.get(Calendar.YEAR);
        int y2 = cal2.get(Calendar.YEAR);

        int m1 = cal1.get(Calendar.MONTH);
        int m2 = cal2.get(Calendar.MONTH);

        if (y2 - y1 >= 0) {
            months = m2 - m1 + 1;
        }
        if (y2 - y1 >= 1) {
            months += 12;
        }
        if (y2 - y1 >= 2) {
            months += 12 * (y2 - y1 - 1);
        }

        return months;
    }
Lin
  • 497
  • 5
  • 15