20

I realize this has been asked a lot. I did actually look. I've spent hours looking around and trying to figure this out. I'm supposed to be making a program that stores what amounts to a list of appointments in a database, with a description, date, start time, and end time. It has to take input from the user to add or cancel appointments, so as far as I know that means I need to convert a string to a date.

These are my imports: import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Time; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Scanner;

As you can see, no java.util.Date there. Here is the bit where I'm getting the error:

private static java.sql.Date getDay()
{
    Scanner in = new Scanner(System.in);
    String input;
    Date apptDay = null;
    DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
    java.sql.Date sqlDate;
    System.out.println("\nPlease enter the date of the appointment, format: yyyy/mm/dd");
    while(apptDay == null)
    {
        try
        {
            input = in.next();
            apptDay = (Date) df.parse(input);
        }
        catch(ParseException e)
        {
            System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
        }
    }
    sqlDate = new Date(apptDay.getTime());
    return sqlDate;
}

I've added java.sql.Dates to it and mucked about with it a bunch trying to get it to work, but it's still giving me this:

Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Date at Calendar.getDay(Calendar.java:47)

Any ideas on what I'm doing wrong or how to make this work would be very much appreciated.

Edit: I thought perhaps it would help if I added the bit of code that is calling this so maybe it will be more clear how I am trying to use it, so here is the addAppointment() method, so you can see where getDay() is being called and where it's going.

public static void addAppointment() throws SQLException
{
    //get the info
    String desc = getDesc();
    java.sql.Date apptDay = getDay();
    Time[] times = getTime();
    Time startTime = times[0];
    Time endTime = times[1];
    int key;

    Connection conn = SimpleDataSource.getConnection(); //connect to the database

    try
    {
        PreparedStatement max = conn.prepareStatement("SELECT MAX(ID) FROM Calendar");
        ResultSet result = max.executeQuery();
        key = result.getInt("ID") + 1; 
        PreparedStatement stat = conn.prepareStatement(
                "INSERT INTO Calendar " +
                "VALUES (?, ?, ?, ?, ?)"); 
        stat.setInt(1, key);
        stat.setString(2, desc); 
        stat.setDate(3, apptDay);
        stat.setTime(4, startTime);
        stat.setTime(5, endTime);
        stat.execute();
        System.out.println("\nAppointment added!\n");
    }
    finally
    {
        conn.close(); //finished with the database
    }
}
Tajha
  • 399
  • 1
  • 5
  • 15

9 Answers9

60

It would be much simpler to change the input format to yyyy-MM-dd and use java.sql.Date.valueOf(String date) method which converts a string in the above format to a java.sql.Date value directly.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • This appears to have worked! Thank you! But now I have the same problem with the Time. Is there something similar to this that will work with hh:mm? (I tried to upvote this, but I'm not cool enough T_T) – Tajha Aug 26 '13 at 08:06
  • It looks like there is also a `Time.valueOf(String x)` but it requires hh:mm:ss format... I'd love to hear if there's an easy way to get rid of the seconds as I don't need them, but I think I can work around that. – Tajha Aug 26 '13 at 08:40
  • 1
    Yes, theres a workaround, ask for hh:mm input format and then add ":00" to the result, then parse... – Evgeniy Dorofeev Aug 26 '13 at 11:31
3

This should work:

private static java.sql.Date getDay()
{
    Scanner in = new Scanner(System.in);
    String input;
    Date apptDay = null;
    DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
    java.sql.Date sqlDate;
    System.out.println("\nPlease enter the date of the appointment, format: yyyy/mm/dd");
    while(apptDay == null)
    {
        try
        {
            input = in.next();
            apptDay = (Date) df.parse(input);
        }
        catch(ParseException e)
        {
            System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
        }
    }
    sqlDate = new java.sql.Date(apptDay.getTime());
    return sqlDate;
}
Jainendra
  • 24,713
  • 30
  • 122
  • 169
  • Should, but apparently doesn't =/ That was the last thing I tried before posting this and it still gave me the error. I'm going to run it again, just to check one more time 'cause I might just be losing my mind from staring at code for more than 12 hours >.< (Not just this problem, I was doing other projects, too) – Tajha Aug 26 '13 at 07:30
  • Can't cast `java.util.Date` to `java.sql.Date`) – Eric Wilson Nov 16 '20 at 19:48
2

java.sql.Date and java.util.Date are two different Classes. You need to convert the sql date into util date which is compatible with Calendar.

  Date jDate =  new Date(sqlDate.getTime());

and vice-versa

  java.sql.Date sqlDate =  new java.sql.Date(jDate.getTime());
rocketboy
  • 9,573
  • 2
  • 34
  • 36
  • Yeah, in my digging I found that they were two different classes. I'm not using the Calendar class, I'm making a Calendar database, for which I presumably need the java.sql.Date, right? I do have that first one in there in an attempt to get it to work (util -> sql). Maybe it would help if I post the bit of code where this is being called? – Tajha Aug 26 '13 at 07:36
  • Ahh, just be aware of what classes are compatible with which Date class. You cannot just type them into each other. – rocketboy Aug 26 '13 at 07:41
  • I know that, but I still don't know how to make this work. I didn't import java.util.Date, so I thought when I converted the string input to a date it would be java.sql.Date (which I could be mistaken, but I think I need for the database shenanigans), but then it pitched the error about casting java.util.Date to java.sql.Date and I started searching for an answer. I made a bunch of modifications to my original code in an attempt to fix it. What you see above is where it wound up when I decided it was time to ask for help. – Tajha Aug 26 '13 at 07:50
  • Naming a class `Calendar` is confusing and asking for trouble. Use another name such as `Cal` to avoid collision with a bundled class name. – Basil Bourque Oct 13 '15 at 16:47
2

The following statement caused the error:

apptDay = (java.sql.Date) df.parse(input);

In fact, the type of the return value of java.text.DateFormat.parse(String) is java.util.Date, which is incomparable with java.sql.Date.

In your situation, the easiest way might be using java.util.Date instead of java.sql.Date.

Another note: your class name Calendar is duplicate with java.util.Calendar. And it is not a good coding style to use class names which are already used by the standard library.

wxl24life
  • 683
  • 1
  • 7
  • 13
  • Don't I need to use java.sql.Date to put it into a database? =/ And re: your other note, I'm a n00b. I didn't realize there was a Calendar in the standard library until I started digging around trying to figure out why this wasn't working ^.^; – Tajha Aug 26 '13 at 07:41
  • 1
    Just to make it simple, you can use both to put it into the database, it might be that its not correct formatted if you use java.util.Date. Important is just, that you use the same Date in the whole programm. – Sarajog Aug 26 '13 at 07:46
  • @Tajha As for your edited version, you need to use `java.sql.Date` in `stat.setDate(3, apptDay);`, then you might need to convert between `java.util.Date` and `java.sql.Date`. – wxl24life Aug 26 '13 at 07:49
  • @Sarajog I had java.sql.Date imported, and before I started messing with it, everything that says java.sql.Date just said Date, but it gave me an error, so I started looking and making changes trying to fix it. @wxl24life I'm not sure what you mean by using it in `stat.setDate(3, apptDay);` ... that apptDay is local to a different method and is of type `java.sql.Date` Right here where it's declared and the `getDay()` method from the original post is called: `java.sql.Date apptDay = getDay();` – Tajha Aug 26 '13 at 07:56
  • @Tajha By mentioning `stat.setDate(3, apptDay)`, I mean you are using `java.sql.PreparedStatement.setDate(int parameterIndex, Date x)` which need a `java.sql.Date`. I'll give my edited answer:-) – wxl24life Aug 26 '13 at 08:02
  • @wxl24life I'm confused.... `apptDay` in the location you're referring to IS a java.sql.Date... see: `java.sql.Date apptDay = getDay();` Or am I just epically failing to understand what you're saying? =/ – Tajha Aug 26 '13 at 08:12
  • @Tajha sorry... I have the assumption that `getDay()` returns a `java.util.Date`, which is my suggestion in my original answer, and I am trying to answer you first reply question -**Don't I need to use java.sql.Date to put it into a database**;-) – wxl24life Aug 26 '13 at 08:17
  • @wxl24life Ahhhh, okay. Thanks for confirming that for me ^.^ As for `getDay()`, that's that block of code at the top, the original one from before I edited... it's _supposed_ to be returning a `java.sql.Date`, but I don't think it is, and I don't know why, hence the dilemma – Tajha Aug 26 '13 at 08:25
1
   sqlDate = new java.sql.Date(apptDay.getTime());
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
  • Yes, I have that in there, and it's still giving me the error. – Tajha Aug 26 '13 at 07:34
  • Or... are you saying that's the part that's giving me the error? – Tajha Aug 26 '13 at 07:44
  • Your code is creating a java.util.Date and what you need is a java.sql.Date – Maurice Perry Aug 26 '13 at 07:54
  • I know I need a java.sql.Date... I don't know why it's creating a java.util.Date. Shouldn't `new java.sql.Date(apptDay.getTime())` make a java.sql.Date? If you tell me no, I will probably believe you because I'm beginning to really think Java is just that evil. – Tajha Aug 26 '13 at 08:15
1
Date.valueOf(scanner.nextLine())
Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
1
String strDate = scanner.nextLine();

SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = format.parse(strDate);
0

Try below method -

private static java.sql.Date getDay() throws SQLException {
    Scanner in = new Scanner(System.in);
    String input;
    java.util.Date utilDay = null;
    DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
    System.out.println("\nPlease enter the date of the appointment, format: yyyy-mm-dd");
    while(utilDay == null){
        try{
            input = in.next();
            utilDay = (java.util.Date) df.parse(input);
        }catch(ParseException e){
            System.out.println("Please enter a valid date! Format is yyyy/mm/dd");
        }
   }

   java.sql.Date sqlDate = new java.sql.Date(utilDay.getTime());
   return sqlDate;
}

And from main() method, call this method -

Date birthday = getDay();
Vikas Sachdeva
  • 5,633
  • 2
  • 17
  • 26
0

java.time

It’s time someone writes the modern answer to this question.

Assuming that you are using (or can start using) a JDBC 4.2 compliant driver you should not use the two Date classes nor DateFormat or SimpleDateFormat. All those classes are poorly designed, the last two particularly troublesome. They are also long outdated. Instead rely on java.time, the modern Java date and time API. It’s much nicer to work with. We need a LocalDate and a DateTimeFormatter.

Now we’re at it, don’t use java.sql.Time either. Use LocalTime from java.time.

So your variable declarations become:

    //get the info
    String desc = getDesc();
    LocalDate apptDay = getDay();
    LocalTime[] times = getTime();
    LocalTime startTime = times[0];
    LocalTime endTime = times[1];
    int key;

Only for passing the java.time objects to your prepared statement you don’t use setDate and setTime. You need to use setObject:

        stat.setInt(1, key);
        stat.setString(2, desc); 
        stat.setObject(3, apptDay);
        stat.setObject(4, startTime);
        stat.setObject(5, endTime);
        stat.execute();

Everything else is as before. For parsing the user input string to a LocalDate, here is a short demonstration:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/M/d");
    String input = "2019/11/09";
    try {
        LocalDate aptDate = LocalDate.parse(input, dateFormatter);
        System.out.println("Parsed date: " + aptDate);
    } catch (DateTimeParseException dtpe) {
        System.out.println("Please enter a valid date. Format is yyyy/mm/dd");
    }

The output from the last snippet is:

Parsed date: 2019-11-09

I have specified just one M and one d in the format pattern string to allow the user to enter one or two digits for month and day of month, for example 2019/11/9. Most users I know will appreciate this.

Link

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161