Search code examples
javadatetimedate-comparisonjdatechooserlocaldate

Wondering how to compare JDateChooser with LocalNow


So I'm trying to create an if else statement where if a date from the jdatechooser is before today's date, then an error message would occur. From my knowledge, you can get today's date as LocalDate.now(), format it into a string, and then do a try-catch to parse it back into a Date. For the jdatechooser, you can grab that as a Date, format it into a string, and then do a try-catch to parse it back into a date as well. The only issue with this is when you do jdate.before(localdate) an error occurs. Is there another method of doing this? I saw that you could get today's date as an Instance, but I don't have much experience with that yet.

This is the code that I tried:

try {
    //Checks to see if New Due Date is a date set before today's date

    //Grabs today's date, converts it into string, then converts it into date
    LocalDate ld = LocalDate.now();
    SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy");
    String tds = sdf.format(ld);
    Date tdd = sdf.parse(tds);

    //Grabs reactivateDateChooser1, converts it into string, then converts it into date
    Date rdc = reactivateDateChooser1.getDate();
    SimpleDateFormat sdf1 = new SimpleDateFormat("MMM dd, yyyy");
    String rdcs = sdf1.format(rdc);
    Date rdcd = sdf1.parse(rdcs);

    //If the new Due Date is before or on today's date, then error message will show
    if(rdcd.before(tdd)){
        JOptionPane.showMessageDialog(null, "Please select a date after " + tds, "Select Valid Date", JOptionPane.ERROR_MESSAGE);
    }

    //If the date chooser is empty, then error message will show
    else if (reactivateDateChooser1.getDate() == null){
        JOptionPane.showMessageDialog(null, "Please select a date", "Needs Date", JOptionPane.ERROR_MESSAGE);
    }

    //Otherwise, if the new date is after today's date, then the function will happen
    else if (rdcd.after(tdd)){
        changeStatusToActive();
        statusCheck1.setText("");
        refreshClassTable();
        closeReactivateDialog();
    }
} catch(Exception e){
    JOptionPane.showMessageDialog(null, e);
}

And this is the error that I'm getting:

java.lang.IllegalArgumentException: Cannot format given Object as a Date

Solution

  •     DateTimeFormatter dateFormatter
                    = DateTimeFormatter.ofPattern("MMM dd, yyyy", Locale.ITALY);
        //Checks to see if New Due Date is a date set before today's date
    
        //Grabs today's date
        LocalDate today = LocalDate.now();
    
        //Grabs reactivateDateChooser1, converts it into LocalDate (if not null)
        Date reactivateUtilDate = reactivateDateChooser1.getDate();
    
        //If the date chooser is empty, then error message will show
        if (reactivateUtilDate == null) {
            JOptionPane.showMessageDialog(null, "Please select a date", 
                        "Needs Date", JOptionPane.ERROR_MESSAGE);
        } else {
            LocalDate reactivateDate = reactivateUtilDate.toInstant()
                        .atZone(ZoneId.of("Asia/Singapore"))
                        .toLocalDate();
    
            //If the new Due Date is before or on today's date, then error message will show
            //Otherwise, if the new date is after today's date, then the function will happen
            if (reactivateDate.isAfter(today)) {
                changeStatusToActive();
                statusCheck1.setText("");
                refreshClassTable();
                closeReactivateDialog();
            } else {
                String todayString = today.format(dateFormatter);
                JOptionPane.showMessageDialog(null, 
                            "Please select a date after " + todayString,
                            "Select Valid Date", JOptionPane.ERROR_MESSAGE);
            }
        }
    

    Rather than converting from the modern LocalDate to the outmoded Date, better to use the modern and better API as much as possible. I know you cannot avoid getting a java.util.Date from your JDateChooser, so first thing convert it to the modern Instant type and do further conversions from there to obtain a LocalDate that you can compare with the one you have. LocalDate has methods isBefore and isAfter for comparing to other LocalDate objects.

    The old date and time classes Date, SimpleDateFormat and friends have proven to be poorly designed, and SimpleDateFormat in particular is notoriously troublesome. Just look at how many questions there are on Stack Overflow about surprising and unwanted behaviour of SimpleDateFormat. All of this is why Oracle issued java.time in 2014 as a replacement. And surely, the modern API is so much nicer to work with. I recommend it warmly.

    I further recommend you specify locale for your formatter (even if you just specify Locale.getDefault()) and time zone for your conversion from Date to LocalDate (even if you go for ZoneId.systemDefault(). So no one needs to be in doubt that a locale and a time zone are used and you have chosen them consciously. Finally I have made an attempt at more explanatory variable names.