3

I’m trying to calculate the number of days between 2 dates. When I run this, it throws the catch (ParseException ex).

import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Main {

    public static void main(String[] args) {

        String date1 = "11/11/2020";
        String date2 = "13/11/2020";

        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-mm-yyyy");
            Date date_1 = dateFormat.parse(date1);
            Date date_2 = dateFormat.parse(date2);

            System.out.println(date_1);
            System.out.println(date_2);

            long numberOfDays = date_2.getTime() - date_1.getTime();
            numberOfDays = TimeUnit.DAYS.convert(numberOfDays, TimeUnit.MILLISECONDS);

            System.out.println(numberOfDays);

        } 
        catch (ParseException ex)
        {
            System.out.println("error");
        }
    }
}

other than the catch, there are no errors, so I’m kind of lost.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
M0nzter
  • 53
  • 5
  • 1
    "other than the catch, there are no errors, so I’m kind of lost."... well, should you maybe print what the exception says? – eis Mar 09 '20 at 13:32
  • 1
    Change date strings to use '-' instead of '/' eg. "11-11-2020". Or change the SimpleDateFormat string to look like this: "dd/mm/yyyy" – mTv Mar 09 '20 at 13:33
  • Statement "it throws the catch (ParseException ex)" is really weird. By it's nature a "catch" block catches the exception, not throws it (well, you can rethrow something inside of it). It is recommended to properly handle the caught expection, eg. at least use `e.printStackTrace();` instead of `System.out.println("error");` – Amongalen Mar 09 '20 at 13:38
  • 2
    As I suggested in my answer, `Date` is quite `deprecated` and should not be used. `LocalDate` is the way to go for date related code. – WJS Mar 09 '20 at 14:27
  • 1
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Also converting milliseonds to days may give inaccurate results across summer time (DST) transistions and similar. Instead use `LocalDate`, `DateTimeFormatter` and `ChronoUnit.DAYS.between()`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Mar 09 '20 at 19:12

6 Answers6

5

Don't use Date. Try this.

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        String date1 = "11/11/2020";
        String date2 = "13/11/2020";

        LocalDate d1 = LocalDate.parse(date1,dtf);
        LocalDate d2 = LocalDate.parse(date2,dtf);

        long ndays = d1.datesUntil(d2).count();
        System.out.println(ndays);
WJS
  • 36,363
  • 4
  • 24
  • 39
4

If you had printed the catched exception:

System.out.println("error: " + ex.getLocalizedMessage());

You would have seen:

error: Unparseable date: "11/11/2020"

The problem is in:

SimpleDateFormat dateFormat = new SimpleDateFormat("dd-mm-yyyy");

change it to:

SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

Since the provided dates are in that format.

jeprubio
  • 17,312
  • 5
  • 45
  • 56
  • 1
    According to the JavaDoc, `mm` stands for minutes. – WJS Mar 09 '20 at 14:08
  • @WJS You are right, well spotted, it had more than one bug then. I update the answer, thanks – jeprubio Mar 09 '20 at 14:11
  • java.time would have made you aware of the incorrect case of `mm`. One more reason to use it instead of the troublesome `SimpleDateFormat`. – Ole V.V. Mar 09 '20 at 19:13
3

Just change this :

 SimpleDateFormat dateFormat = new SimpleDateFormat("dd-mm-yyyy");

to that :

SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

The date you are trying to parse 11/11/2020 does not match the date format you are trying to use dd-mm-yyyy

You can resolve problems like that on your own by printing out the stack trace inside catch :

ex.printStackTrace();
Thanos M
  • 604
  • 6
  • 21
3

If Java 8 is an option I'd recommend using the Time API.

Example:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class Main
{
    public static void main(String[] args) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        String date1 = "11/11/2020";
        String date2 = "13/11/2020";

        LocalDate firstDate = LocalDate.parse(date1, format);
        LocalDate secondDate = LocalDate.parse(date2, format);

        long days = ChronoUnit.DAYS.between(firstDate, secondDate);
        System.out.println("Days between: " + days);
    }
}
2

First, you have different formats in input dates and defined format. Therefore, you're getting a parsing exception.

Secondly, We can java.time.Duration class in Java8 for such calculation. Example:

public static void main(String[] args) throws ParseException {
    String date1 = "11/11/2020";
    String date2 = "13/11/2020";
    DateFormat format = new SimpleDateFormat("dd/MM/yyyy");

    Duration duration = Duration.between(format.parse(date1).toInstant(), format.parse(date2).toInstant());
    System.out.println("Days between: " + duration.toDays());
}
Tayyab Razaq
  • 348
  • 2
  • 11
  • I agree that using java.time since Java 8 is a great improvement. Still better: (1) Drop the use of the old `DateFormat`, `SimpleDateFormat` and `Date` completely. (2) Use `ChronoUnit.DAYS.between()` rather than `Duration`. BTW lower case `mm` is incorrect for month. – Ole V.V. Mar 09 '20 at 19:09
  • Thanks @OleV.V 1 & 2 are good suggestions 3) `mm` is working fine with `SimpleDateFormat ` but not work in `DateTimeFormatter`. – Tayyab Razaq Mar 09 '20 at 19:29
  • Oooh! My bad. I did not notice that. You're right. Thanks – Tayyab Razaq Mar 09 '20 at 20:22
1

Your pattern is incorrect.

You use:

new SimpleDateFormat("dd-mm-yyyy");

but you need use:

new SimpleDateFormat("dd/mm/yyyy");

because yours date's have "/" instead of "-"

Nahuel Giani
  • 540
  • 6
  • 16