Jack Mc Lauren
Jack Mc Lauren

Reputation: 395

Joda library does not work properly

I'm using Joda library in my android application to calculate the duration between two given dates. Using this application to calculate a person's age. The following code gives this output : 23 years 11 months and 6 days

DateTime from_readable_dateTime = new DateTime(from_date_dt);
DateTime to_readable_dateTime = new DateTime(to_date_dt);
Period period = new Period(from_readable_dateTime, to_readable_dateTime);

from_date_dt in this case is 1990/01/06 and to_date_dt is 2014/09/15. (date format is yyyy/mm/dd). As I mentioned earlier the output of this piece of code with the given inputs must be 24 years, 7 months and 20 days while I get 23 years 11 months and 6 days. What's the problem? Am I doing something wrong or Joda is faulty?

UPDATE-1

I get 3 numbers as year, month and day from 3 number pickers I make a single string as date(start date variable is named from_date_string and end date is named to_date_string), I convert these two strings to date variables (from_date_dt and to_date_dt):

from_date_dt = null;
to_date_dt = null;
diff_dt = null;
dateFormat = new SimpleDateFormat("yyyy/mm/dd"); 
try {
       from_date_dt = dateFormat.parse(from_date_string);
       to_date_dt = dateFormat.parse(to_date_string);
    } catch (ParseException e) {
       e.printStackTrace();
    }

BTW, I'm working with Persian calendar. Since I can't use the default date picker, I'm using number pickers as date pickers.

Upvotes: 1

Views: 244

Answers (1)

Meno Hochschild
Meno Hochschild

Reputation: 44071

The standard period type which you implicitly use contains weeks. The class Period has another constructor with 3 arguments where you can specify PeriodType.yearMonthDay() as third argument.

LocalDate d1 = new LocalDate(1990, 1, 6);
LocalDate d2 = new LocalDate(2014, 9, 15);
Period p = new Period(d1, d2, PeriodType.yearMonthDay());
System.out.println(p); // output: P24Y8M9D

To explain the result in fine-granular steps:

[1990-01-06] + 24 years = [2014-01-06]
[2014-01-06] + 8 months = [2014-09-06]
[2014-09-06] + 9 days = [2014-09-15]

Another thing to consider, don't use DateTime if your input is just a plain date format. Do you really want to take into account timezone effects? And why do you use SimpleDateFormat although JodaTime has its own formatters?

UPDATE after updated question of OP:

Now the question has become a lot clearer.

First to note generally, if you use number pickers then your original input for year, month and day-of-month are just integers. In that case I would normally not use a formatter at all, but just pass the numbers to the constructor of LocalDate. This constructor will also verify the input automatically. The complex conversion you try is very error-prone (number to string, then string concatenation to a date string, then parsing it with your default timezone and then passing java.util.Date to DateTime-ctor). It can be completely avoided.

Second to note and most important: You write that you use a persian calendar. Then the reason why you cannot use the default date picker is simply that this default date picker does not support the calendrical rules of persian calendar. Is my speculation right? And here the very bad news for you: Jodas classes do NOT support the persian calendar, too, especially LocalDate or DateTime are only designed for the ISO-8601-standard which is based on the modern proleptic gregorian calendar. Month lengths for example are different in gregorian calendar and in persian calendar, hence a completely different calendar arithmetic is required which is not supported by Joda-Time.

So your strange period results are probably explainable by the fact that you tried to let the user define persian year, month and day. And then you try to parse this input leniently (otherwise Joda-Time would immediately complain about odd day-values for example). But the last step - period calculation - must fail because it is based on ISO-8601 in Joda-Time and not persian calendar rules.

Am I right? Or have I misinterpreted your updated question?

A work-around is difficult. If you really want to have period calculation for a persian calendar then you have to build it from the scratch. As far as I know there is actually no library which supports this feature. A guideline for writing a persian solution can be the algorithm discussed in this SO-post however.

UPDATE indicating a solution:

Meanwhile I have implemented the Persian calendar in Time4A, see also this SO-post. So if you are able to use Time4A and combine the PersianCalendar with the algorithm for a multi-unit-period mentioned above then this will solve your problem. Time4A-v3.15-2016a explicitly supports special Persian calendar units which use different rules than gregorian calendar units.

Upvotes: 2

Related Questions