0

Hello i need to get count day between to date using ChronoUnit

this is my code :

            Date madate = rfxobjet.getRv_rc_date();
            Date date=java.util.Calendar.getInstance().getTime();
            Date res=null;
            int day = ChronoUnit.DAYS.between(madate,date);

but i got this error : The method between(Temporal, Temporal) in the type ChronoUnit is not applicable for the arguments (Date, Date)

please what i should to do i need to resolve this error

mehdi hanine
  • 113
  • 1
  • 4
  • 11
  • 1
    Use one of the [`java.time`](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) types instead of `Date`. – Powerlord Jun 28 '20 at 13:42
  • 1
    Never use the legacy classes `Date` or `Calendar`. Use only classes from the *java.time* packages. – Basil Bourque Jun 28 '20 at 16:59
  • Does this answer your question? [Calculating days between two dates with Java](https://stackoverflow.com/questions/20165564/calculating-days-between-two-dates-with-java) – Ole V.V. Jun 28 '20 at 19:55

3 Answers3

1

You mix different API. Date is an old class which was in Java since JDK 1. While ChronoUnit is from newer date API appeared first from JDK8. Normally you should use newer API. It means that instead of Date you should use LocalDate (or LocalDateTime) which is part of the new API.

So in order to correct your code you need to make so that madate and date are both instances of LocalDate. E.g. this should work:

LocalDate madate = LocalDate.now();
LocalDate date = LocalDate.now();
long day = ChronoUnit.DAYS.between(madate, date);

Or if you need still need to use Date objects you can convert them to Temporal objects:

Date madate = rfxobjet.getRv_rc_date();
Date date = java.util.Calendar.getInstance().getTime();
long day = ChronoUnit.DAYS.between(madate.toInstant(), date.toInstant());

Temporal is a base class for LocalDate and LocalDateTime so using Date.toInstant() you essentially convert date to corresponding instance in new API.

NB. between() returns long so the day variable also needs to be of type long or you need to use to int conversion:

int day = (int) ChronoUnit.DAYS.between(madate, date);
igorpcholkin
  • 947
  • 7
  • 15
  • Almost correct. `ChronoUnit.DAYS.between(madate.toInstant(), date.toInstant());` counts a day as always 24 hours. A day is not always 24 hours, so you may get a date too many or too few occasionally. – Ole V.V. Jun 28 '20 at 19:51
1
Date madate = rfxobjet.getRv_rc_date();//please consider renaming this variable
LocalDate madataLocalDate = Instant.ofEpochMilli(madate.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate now = LocalDate.now();
long day = ChronoUnit.DAYS.between(madataLocalDate, now);

Basically you need to use classes from the java.time package, you can't mix between java.util.Date and java.time.LocalDate.

mohammedkhan
  • 953
  • 6
  • 14
  • @OleV.V. hmm, weird. I've edited it so both dates are `LocalDate` see if that works. – mohammedkhan Jun 29 '20 at 14:08
  • 1
    It works now, thank you. I don’t find it that weird. From the documentation of `between()`: *The implementation will convert the second type to be an instance of the first type before the calculating the amount.* We cannot convert a `LocalDate` to `LocalDateTime` since we don’t know the time of day (the opposite conversion goes well). – Ole V.V. Jun 29 '20 at 16:28
1

You should stop using the outdated and error-prone java.util date-time API and switch to the modern date-time API.

If rfxobjet.getRv_rc_date() returns an object of java.util.Date, your first step should be to convert it into an object of type, Instant by calling Date#toInstant on this object i.e.

Date madate = rfxobjet.getRv_rc_date();
Instant instant = madate.toInstant();

Once you have an object of Instant, you can convert it to any other modern date-time object as per your requirement e.g.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.now();
        // I've used the time-zone of Europe/London as an example, you can choose any
        // time-zone as per your requirement. You can also select the time-zone used by
        // your JVM, ZoneId.systemDefault()
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));
        OffsetDateTime odt = zdt.toOffsetDateTime();
        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(instant);
        System.out.println(zdt);
        System.out.println(odt);
        System.out.println(ldt);
    }
}

Output:

2020-06-28T16:58:27.725618Z
2020-06-28T17:58:27.725618+01:00[Europe/London]
2020-06-28T17:58:27.725618+01:00
2020-06-28T17:58:27.725618

Note: LocalDateTime drops off information like Zone Offset and Zone ID which may be required in your business logic. Therefore, choose the appropriate class as per the table shown below (Ref): enter image description here

Back to your problem:

Now that you have an object of Instant, you can get an instance of LocalDateTime as described above i.e.

ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDateTime ldt = zdt.toLocalDateTime();

The final step is to get the number of days between now and ldt which you can do as follows:

LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
long days = ChronoUnit.DAYS.between(ldt, now);

Note that I've passed ZoneId as the parameter to LocalDateTime.now just as the recommended practice so that you can specify the required ZoneId as per your requirement. If you do not pass this parameter, it will use ZoneId.systemDefault() by default.

The complete code:

Date madate = rfxobjet.getRv_rc_date();
Instant instant = madate.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDateTime ldt = zdt.toLocalDateTime();
LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
long days = ChronoUnit.DAYS.between(ldt, now);
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110