2

I'm using below code to calculate No of Years, Months and days between two dates using Joda-Time

public void getDateDiff(View view) {

    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy").withLocale(Locale.US);
    DateTime startDate = null;
    DateTime endDate = null;

    // expected output 23...2....29

    try {
        startDate = formatter.parseDateTime("01/09/1995");
        endDate = formatter.parseDateTime("30/11/2018");

        Period period = new Period(startDate, endDate);

        Log.e("No Of Years : ", period.getYears() + " Years, ");
        Log.e("No Of Months : ", period.getMonths() + " Months, ");
        Log.e("No Of Days : ", period.getDays() + " Days, ");

        tvResult.setText(String.format("No Of Years : %d Years, \nNo Of Months : %d Months, \nNo Of Days : %d Days, ", period.getYears(), period.getMonths(), period.getDays()));

    } catch (Exception e) {
        e.printStackTrace();
    }


}

The expected output of above code is( checked using this site and using one app in google play store)

23 years, 2 months, 29 days

but I'm getting below result using same date

/goku.com.demo E/No Of Years :: 23 Years, 
/goku.com.demo E/No Of Months :: 2 Months, 
/goku.com.demo E/No Of Days :: 1 Days, 

Can any one help me to find issue what I'm missing in above code

I'm using using below joda-time Dependency.

implementation 'joda-time:joda-time:2.9.9'

P.S. already checked below links

If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.

Goku
  • 9,102
  • 8
  • 50
  • 81
  • Have you tried supplying `PeriodType.yearMonthDay()` as third argument to the `Period` constructor? – MC Emperor Nov 30 '18 at 07:08
  • @MCEmperor No can u explain more about `PeriodType.yearMonthDay()` because i'm totally new in `joda-time` and thanks for the response – Goku Nov 30 '18 at 07:10
  • 1
    And have you considered migrating to the new Java Date and Time API, from the `java.time` package? – MC Emperor Nov 30 '18 at 07:10
  • @MCEmperor if you any solution using `Java Date and Time API` feel free to past an answer – Goku Nov 30 '18 at 07:11
  • FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), advising migration to the [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Nov 30 '18 at 08:42
  • @BasilBourque sir thank so much for this info using `Java 8 Date and Time API` in my android project its required `API level 26` while my min API level is 21 is there any other way i can use `Java Date and Time API` in API level 21 – Goku Nov 30 '18 at 08:51
  • Most of the *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Nov 30 '18 at 08:56
  • FYI, *Joda-Time*, *java.time*, and *ThreeTen-Backport* are all led by the same man, [Stephen Colebourne](https://stackoverflow.com/users/38896/jodastephen). He designed the API of the backport to mimic as closely as possible the API of *java.time*. Later, if you ever want to migrate to the built-in classes and away from the back-port, you will need do little more than change your `import` statements. – Basil Bourque Nov 30 '18 at 08:58

3 Answers3

6

The reason that your Joda Time code does not work, is because if you don't provide a PeriodType object, then the standard PeriodType is used. The standard period type defines not only years, months and days to be included in the Period calculation, but also weeks. And you're not displaying the number of weeks, which is 4 in your case. If you write period.getWeeks() it'll return 4.

In order to make it work, you have to provide a PeriodType as third argument to the Period constructor. If you change the declaration of period to

Period period = new Period(startDate, endDate, PeriodType.yearMonthDay());

then it'll work. The period calculation will then only use the year, month and day fields.

But

...it is better to migrate to the new Java Date and Time API available in the java.time package, if you are using Java 8 or above. Don't get me wrong, Joda Time is a very good date and time API. Java 8's date and time API is heavily influenced on Joda Time, because of its quality. Its lead developer is actually the same person, Stephen Colebourne.

But Joda Time is now in maintenance mode, and on its website users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Using Java 8 Date and Time API

DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/yyyy").withLocale(Locale.US);

// expected output 23...2....29
LocalDate startDate = LocalDate.parse("01/09/1995", f);
LocalDate endDate = LocalDate.parse("30/11/2018", f);
Period period = Period.between(startDate, endDate);

Backport to Java 6 and 7; Android support

Most of the java.time functionality is back-ported to Java 6 and Java 7 in the ThreeTen-Backport project, also led by Stephen Colebourne. Further adapted for earlier Android API levels (below 26) in the ThreeTenABP project. See How to use ThreeTenABP.

Note that there are some differences between Joda Time and the Java Date and Time API. In particular, the Period class from the Java Date and Time API is less comprehensive. However, the Period class from the Java Date and Time API provides the functionality which meets your requirement.


I see that this code using java.time is actually the same as @MaxXFrenzY's. This is not because of copy-paste, that is because the new Java Date and Time API is designed to be both unambiguous and straightforward.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • Please use `yearMonthDay()` instead of `yearMonthDayTime()` which takes better into account the fact that the OP is not interested in the time part. And for the record: `java.time.Period` only works because by accident it supports exactly what the OP wants but else offers a very limited choice of period types (only one) compared with Joda-Time. – Meno Hochschild Nov 30 '18 at 11:05
  • @MenoHochschild I've updated the code. I was looking for more information about Joda Time, and [then I found this](https://stackoverflow.com/a/24635657/507738) – that's right, your own post. ;-) I'll include it in the answer. – MC Emperor Nov 30 '18 at 12:28
5

With Java 8 time API it would be easy to achieve the result using DateTimeFormatter and LocalDate.

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
....

    public void test() {
        DateTimeFormatter formatter = 
        DateTimeFormatter.ofPattern("dd/MM/yyyy").withLocale(Locale.US);
        LocalDate startDate = LocalDate.parse("01/09/1995", formatter);
        LocalDate endDate = LocalDate.parse("30/11/2018", formatter);

        Period period = Period.between(startDate, endDate);
        System.out.println(String.format("No Of Years : %d Years, \nNo Of Months : %d Months, \nNo Of Days : %d Days, ",
                period.getYears(), period.getMonths(), period.getDays())
        );
    }

The result printed is:

No Of Years : 23 Years, 
No Of Months : 2 Months, 
No Of Days : 29 Days, 
MaxXFrenzY
  • 51
  • 7
-2

You can do this without Joda-Time There can be used wrong milliseconds for types but it will look like this

     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", 
     Locale.getDefault());
     final Date startdate = format.parse("2018-10-20 23:34:32");
     final Date enddate = format.parse("2019-09-19 23:34:32");
     long n = enddate.getTime() - startdate.getTime();
                    if (n>0) {
                        long year, month, day, hour, minute, second;
                        // year = 365 days
                        year = (n/31536000000);
                        if (year != 0)
                            n = n - (year * 31536000000);
                        // month = 30 Days
                        month = (n/2592000000);
                        if (month != 0)
                            n = n - (month * 2592000000);
                        day = (n / 86400000);
                        if (day != 0)
                            n = n - (day * 86400000);
                        hour = (n / 3600000);
                        if (hour != 0)
                            n = n - (hour * 3600000);
                        minute = (n / 60000);
                        if (minute != 0)
                            n = n - (minute * 60000);
                        second = (n / 1000);
                     }