Akyo
Akyo

Reputation: 149

Strange behavior with Joda-Time in period calculation

About the February month, there is a strange behavior that you can see in the incorrect results with Joda-Time, you can look down here:

DateTime date1 = new DateTime(2013, 4, 28, 0, 0, 0, 0);
DateTime date1PlusNineMonths = new DateTime(2014, 1, 28, 0, 0, 0, 0);
Period period1 = new Period(date1, date1PlusNineMonths);
//Correct result
System.out.print(date1.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date1.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period1.getYears() + "Years/" + period1.getMonths() + "Months/" + period1.getWeeks() + "Weeks/" + period1.getDays() + "Days");

DateTime date2 = new DateTime(2013, 4, 29, 0, 0, 0, 0);
DateTime date2PlusNineMonths = new DateTime(2014, 1, 28, 0, 0, 0, 0);
Period period2 = new Period(date2, date2PlusNineMonths);
//Correct result
System.out.print(date2.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date2.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period2.getYears() + "Years/" + period2.getMonths() + "Months/" + period2.getWeeks() + "Weeks/" + period2.getDays() + "Days");

DateTime date3 = new DateTime(2013, 5, 28, 0, 0, 0, 0);
DateTime date3PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period3 = new Period(date3, date3PlusNineMonths);
//Correct result
System.out.print(date3.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date3.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period3.getYears() + "Years/" + period3.getMonths() + "Months/" + period3.getWeeks() + "Weeks/" + period3.getDays() + "Days");

DateTime date4 = new DateTime(2013, 5, 29, 0, 0, 0, 0);
DateTime date4PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period4 = new Period(date4, date4PlusNineMonths);
//Incorrect result
System.out.print(date4.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date4.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period4.getYears() + "Years/" + period4.getMonths() + "Months/" + period4.getWeeks() + "Weeks/" + period4.getDays() + "Days");

DateTime date5 = new DateTime(2013, 5, 30, 0, 0, 0, 0);
DateTime date5PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period5 = new Period(date5, date5PlusNineMonths);
//Incorrect result
System.out.print(date5.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date5.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period5.getYears() + "Years/" + period5.getMonths() + "Months/" + period5.getWeeks() + "Weeks/" + period5.getDays() + "Days");

DateTime date6 = new DateTime(2013, 5, 31, 0, 0, 0, 0);
DateTime date6PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period6 = new Period(date6, date6PlusNineMonths);
//Incorrect result
System.out.print(date6.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date6.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period6.getYears() + "Years/" + period6.getMonths() + "Months/" + period6.getWeeks() + "Weeks/" + period6.getDays() + "Days");

DateTime date7 = new DateTime(2013, 6, 1, 0, 0, 0, 0);
DateTime date7PlusNineMonths = new DateTime(2014, 3, 1, 0, 0, 0, 0);
//Correct result
Period period7 = new Period(date7, date7PlusNineMonths);
System.out.print(date7.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date7.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period7.getYears() + "Years/" + period7.getMonths() + "Months/" + period7.getWeeks() + "Weeks/" + period7.getDays() + "Days");

Normally in the test (period4, period5, period6) I should have days changing rather than showing 9month and 0days each time, is this normal, maybe I'm wrong in my use of the joda framework and the output becomes correct when I do an .addMonth(9) on 01/06/2013.

Output:

28/04/2013.plusMonths(9) = 28/01/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

29/04/2013.plusMonths(9) = 29/01/2014 //correct result

0Years/8Months/4Weeks/2Days //correct calculation

28/05/2013.plusMonths(9) = 28/02/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

29/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 29/02/2014

0Years/9Months/0Weeks/0Days //correct calculation

30/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014

0Years/9Months/0Weeks/0Days //incorrect calculation, should be 0Years/8Months/4Weeks/2Days

31/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014

0Years/9Months/0Weeks/0Days //incorrect calculation, should be 0Years/8Months/4Weeks/1Days

01/06/2013.plusMonths(9) = 01/03/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

Upvotes: 2

Views: 493

Answers (3)

Meno Hochschild
Meno Hochschild

Reputation: 44071

Sorry that just now there is absolutely no solution for you. I suppose the joda architect S. Colebourne must even insist on his way of period calculation due to backward compatibility issues. Anyway, he has closed the corresponding issue on joda-time/github as not-a-bug/won't-fix. If you follow the link given there, he says in his update of javadoc of joda his way of period calculation is correct because

[2013-05-29] + P9M = [2014-02-28]

In my opinion this argument is rather weak because it is also true that

[2013-05-29] + P8M30D = [2014-02-28]

So based on addition-arithmetic only there is no clear indication which period is correct. To unambigously specify the behaviour of period calculation it would be a much better solution if there is something like following specification: If the day of month in end date is smaller than the day of month in start date then the difference should not be counted as full month. Simple and understandable. I am also not convinced that weeks should be a primary part of period calculation because the state of a LocalDate is only based on years, months and days. So instead of saying P8M4W2D (not compatible with ISO-8601!) the solution P8M30D is preferrable.

Upvotes: 0

Akyo
Akyo

Reputation: 149

I did a mistake because I was tired lol I don't know why I was sure that 2014 was a leap year but any way I fact I was more focused on the calculation of months and days If you look a bit here :

        DateTime date4 = new DateTime(2013, 5, 29, 0, 0, 0, 0);
        DateTime date4PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
        Period period4 = new Period(date4, date4PlusNineMonths);
        //Incorrect result
        System.out.print(date4.toString("dd/MM/YYYY")+".plusMonths(9) = "+ date4.plusMonths(9).toString("dd/MM/YYYY"));
        System.out.print(period4.getYears() +"Years/"+ period4.getMonths() +"Months/"+ period4.getWeeks() +"Weeks/"+ period4.getDays() +"Days");

Output :

0Years/9Months/0Weeks/0Days

This is an incorrect calculation It should be 0Years/8Months/4Weeks/2Days Isn't it...?

If it is correct so why when I increase two days more (30 and 31) it always give me the same calculation (0Years/9Months/0Weeks/0Days) we all agree that days are decreasing or am I dreaming...?

Now maybe I wrong in my use of the joda framework because in the app I develop I do a check everyday on a period to have the precise month separation between two date (toDay and the next date) and if I have 9months and 1day it's too late I need to have 9months and 0days as required in my app =/

If I wrong how can I achieve this please...?

Upvotes: 0

Ilya
Ilya

Reputation: 29693

Why do you think that this result is incorrect?
Month is not number of days. Month is abstract unit

So last day of month plus month is last day of next month and not the first day of month after next month.

Why do you think that

30/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014

why not 02/03/2014?

You are wrong in your hypothesis. Joda time works well in your example

Upvotes: 2

Related Questions