-1

I need to manipulate with dates according my task. To be precise I need to check that we have month difference between 2 dates as integer. 2 dates- input arguments. Result - boolean: true if month count is exact(without tail) false otherwise.
For example:

diff_months between 31.01.2018 and 28.02.2018 should be 1 month and it is possible combination.
30.01.2018 and 28.02.2018 : 1 month without tail, so ok
29.01.2018 and 28.02.2018 : 1 month without tail, so ok
28.01.2018 and 28.02.2018 : 1 month without tail, so ok
27.01.2018 and 28.02.2018 : 0 months

lets take another arguments:
28.02.2018 and 28.03.2018 : 1 month without tail, so ok
28.02.2018 and 29.03.2018 : 1 month +1 day, so fail
28.02.2018 and 27.03.2018 : 0 month with tail, so fail

I found that java date api has special API for date calculation but from my point of view it works contradictory:

LocalDate.of(2018, 1, 31).until(LocalDate.of(2018, 2, 28), ChronoUnit.MONTHS); //  0     
LocalDate.of(2018, 1, 31).plusMonths(1); // but 2018-02-28

The second result is expected but firs - not. It looks really weird.

Can you please advise method for month count calculation between two dates which works in contract with the LocalDate#plusMonths method ?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
  • Can you state your definition of month difference in plain English? Your examples are not clear. By the way, use standard ISO 8601 formats (YYYY-MM-DD) when presenting example dates here, for readability. And what is a “tail” on a month? And search Stack Overflow before posting. This Question is likely a duplicate. I’m voting to close as “unclear”. – Basil Bourque Jun 22 '18 at 17:24
  • @Basil Bourque, it is joda time format. It is not duplicate – gstackoverflow Jun 22 '18 at 18:07

2 Answers2

1

Expressing the difference between dates in calendar terms is ambiguous. The Period between jan 31 and feb 28 can be "1 month 0 days" or "0 months 28 days". Both answers are strictly correct.

If you want to implement your particular logic for determining if two dates are line up with plusMonths, java.time gives you all the tools. First, get the number of months between dates without regard for days of the month and then use plusMonths to test:

boolean isExactMonths(LocalDate a, LocalDate b) {
    long months = ChronoUnit.MONTHS.between(YearMonth.from(a), YearMonth.from(b));
    return a.plusMonths(months).equals(b);
}
Misha
  • 27,433
  • 6
  • 62
  • 78
  • *ChronoUnit.MONTHS.between("31.01.2018", "28.02.2018")* returns 0 but I expect 1 – gstackoverflow Jun 22 '18 at 18:12
  • @gstackoverflow Correct, but the code in the answer, `ChronoUnit.MONTHS.between(YearMonth.from(a), YearMonth.from(b))` uses `YearMonth` and therefore returns 1 as you said you expected. I tested this code with the seven examples from your question. Output agrees without put from my answer, which I believe agrees with what you intended. Plus this code is *much* more elegant than mine. – Ole V.V. Jun 25 '18 at 02:51
0

Joda time works as expected:

Months.monthsBetween(org.joda.time.LocalDate.parse("2018-1-31"),org.joda.time.LocalDate.parse("2018-2-28")).getMonths() //1
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710