0

I need to convert a string in the format i.e. "jan 25,2021" to a java.sql.date in the format "2021-01-25". I tried to use this code:

String date = "jan 25,2021";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
java.sql.Date booking_date=null;
try{
java.util.Date util_date = format.parse(date);
booking_date = new Date(util_date.getTime());
}
catch(ParseException e){
            System.out.println(e);
        }

But always throws a ParseException. Where is the mistake?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Martha
  • 35
  • 1
  • 8
  • 3
    I recommend you don’t use `java.sql.Date`. That class is poorly designed and long outdated. Instead use `LocalDate` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). See [Insert & fetch java.time.LocalDate objects to/from an SQL database such as H2](https://stackoverflow.com/questions/43039614/insert-fetch-java-time-localdate-objects-to-from-an-sql-database-such-as-h2). – Ole V.V. Jan 25 '21 at 14:39
  • 2
    The string should be normalized in the UI (or client) to some standard format such as the "ISO format" `2021-01-25`. Then, converting it to a Date, Timestamp, LocalDate, etc. is simple. – The Impaler Jan 25 '21 at 14:48

3 Answers3

3

I need to convert a string in the format i.e. "jan 25,2021" to a java.sql.date in the format "2021-01-25". I tried to use this code:

That's like asking: "How do I convert a painting into an audio file" - these 2 concepts are unrelated. They sound related (jan 25, 2021 is a date, and, well, java.sql.Date, it's right there in the name, isn't it), but they are not: java.sql.Date is a misnomer - it does not represent a date at all; it represents an instant in time. Which is not a date: If I clap my hands and ask everybody around the world what date it is when I did that, you'll get at least 2 different answers, thus proving that these 2 are not the same.

The right solution is to use the newer API which doesn't suffer from such errors:

DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("MMM dd,uuuu", Locale.ENGLISH);
LocalDate ld = LocalDate.parse("jan 25,2021", FORMAT);

I would expect .setObject(x, someLocalDate) to work as a date value, but if it doesn't (and it may not - mysql is notoriously bad, and its JDBC driver is dubious as well), at least convert from the proper representation (LocalDate) to the broken one (java.sql.Date) as late as possible - don't let that error infect your java code. Same goes in reverse: When retrieving dates, use .getObject(idx, LocalDate.class), and if that does not work, convert from the broken java.sql.Date to the correct java.time.LocalDate immediately, prevent that error from infecting your java code as much as possible.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • 3
    An answer with a lot of good information. Details: (1) The month names begin with an upper case letter in English. To accept `jan` with lower case `j` we need a `DateTimeFormatterBuilder` and its `parseCaseInsensitive` method. (2) It’s unclear whether it is a requirement to accept `feb 5` with a 1 digit day of month too. If it is, use only one `d` in the format pattern string. It will still accept `25` with two digits. – Ole V.V. Jan 25 '21 at 15:37
1

I need to convert a string in the format i.e. "jan 25,2021" to a java.sql.date in the format "2021-01-25".

A date-time object is supposed to store the information about date, time, timezone etc., not about the formatting. You can format a date-time object into a String with the pattern of your choice using date-time formatting API.

  • The date-time formatting API for the modern date-time types is in the package, java.time.format e.g. java.time.format.DateTimeFormatter, java.time.format.DateTimeFormatterBuilder etc.
  • The date-time formatting API for the legacy date-time types is in the package, java.text e.g. java.text.SimpleDateFormat, java.text.DateFormat etc.

Switch to the modern date-time API

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. The java.sql.Date extends java.util.Date and thus inherits the same problems. It is recommended to stop using them completely and switch to the modern date-time API.

Using the modern date-time API:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDate = "jan 25,2021";
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                    .parseCaseInsensitive() //For case-insensitive parsing
                                    .appendPattern("MMM d,uuuu")
                                    .toFormatter(Locale.ENGLISH);

        LocalDate date = LocalDate.parse(strDate, dtf);
        System.out.println(date);
    }
}

Output:

2021-01-25

Once parsed into LocalDate, you can use it with JDBC 4.2 onwards as follows (assuming that the column type is DATE):

LocalDate localDate = LocalDate.now();
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, localDate);
st.executeUpdate();
st.close();

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

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

Your supplied format is in the not in the form of year-month-day like the text your formatter expects (i.e. "2021-01-25), so use this instead:

SimpleDateFormat format = new SimpleDateFormat("MMM dd,yyyy");

And you'll be able to correctly parse the date in your format. Otherwise change the argument itself to match the expected pattern (i.e. pass "2021-01-25" as the string).

Edit: This is strictly referring to the code at hand and the format mismatch. See the other, fuller answers for using the newer (and better) APIs that address issues with the old time-related libraries.

Tom V.
  • 1
  • 1
  • 2
  • Not a bad idea, but the format with a `MMM` is locale dependent. The OP will need to make sure the locale is correct (country/dialect) either in the app, or at the server level. If DevOps change the server locale, the whole application may stop working. – The Impaler Jan 25 '21 at 14:52
  • 2
    SDF = mostly broken, and this lacks locale settings. – rzwitserloot Jan 25 '21 at 15:12