1

The question is to calculate the days between two dates. Here's my code

public static void main(String[] args) throws ParseException  {
    // TODO Auto-generated method stub
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd)");
    Scanner input=new Scanner(System.in);
    String date1=input.nextLine();
    String date2=input.nextLine();
    Date d1 =sdf.parse(date1);
    Date d2= sdf.parse(date2);
    if(d1.getTime()>d2.getTime()) {
        System.out.println(d2.getTime()-d1.getTime()/(24*60*60*1000));
    }
    else
        System.out.println(d1.getTime()-d2.getTime()/(24*60*60*1000));

and output is

2010/05/29
2010/01/01
Exception in thread "main" java.text.ParseException: Unparseable date: "2010/05/29"
        at java.base/java.text.DateFormat.parse(DateFormat.java:396)
        at HW10_09156136_1092.HW10_Ex01.main(HW10_Ex01.java:15)
Dice Highe
  • 23
  • 1
  • 5
  • 5
    Because adding the throws clause to a method does not prevent that exception from being thrown. Quite the opposite. It just marks that method as possibly throwing that exception so that callers can handle it in a try-catch-block if they want to. But as the main method is the entry point there is no special handling. – OH GOD SPIDERS Jun 12 '21 at 13:55
  • 3
    The solution to your problem is not to try to handle the exception in any way. Instead you need to look at why the exception happens and modify your code so that it doesn't get thrown. In your case you are trying to parse a date where year, month and day are separated by `/`, but in your dateformat you are using a format where you use `-`. – OH GOD SPIDERS Jun 12 '21 at 13:58
  • (1) Don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalDate` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). (2) Don’t do your own time math. Yours is also incorrect. Leave date and time math to the library methods. (3) When entering you own code into a method, remove the comment `// TODO Auto-generated method stub`. – Ole V.V. Jun 15 '21 at 18:19

1 Answers1

2

You have used m [Minute in hour] at the place of M [Month in year].

Your input has / as the separator whereas you have specified - for it in the parser. The input should match the pattern specified with the parser.

Apart from this, the java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Demo using java.time, the modern Date-Time API:

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

public class Main {
    public static void main(String[] args) {
        String strDateStart = "2021-06-09";
        String strDateEnd = "2021-06-12";
        LocalDate dateStart = LocalDate.parse(strDateStart);
        LocalDate dateEnd = LocalDate.parse(strDateEnd);
        long days = ChronoUnit.DAYS.between(dateStart, dateEnd);
        System.out.println(days);
    }
}

Output:

3

ONLINE DEMO

The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.

Learn more about the modern Date-Time API from Trail: Date Time.

Using the legacy API:

Avoid performing calculations yourself if there already exists an API for the same e.g. the following code uses Math#abs and TimeUnit#convert to avoid error-prone if-else and calculations.

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

public class Main {
    public static void main(String[] args) throws ParseException {
        String strDateStart = "2021-06-09";
        String strDateEnd = "2021-06-12";
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        Date dateStart = sdf.parse(strDateStart);
        Date dateEnd = sdf.parse(strDateEnd);
        
        long millisInOneDay = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
        long days = Math.abs((dateEnd.getTime() - dateStart.getTime()) / millisInOneDay);
        
        System.out.println(days);
    }
}

ONLINE DEMO

After i added throws ParseException, the parse excception still occured, why?

Adding the throws clause to a method forces the caller of the method to either handle the exception using try-catch or rethrow it. It is not a way to prevent the exception from being thrown. Learn more about it from this excellent tutorial from Oracle.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110