"EEE MMM dd HH:mm:ss ZZZ yyyy" date format to java.sql.Date

I am trying to convert EEE MMM dd HH:mm:ss ZZZ yyyy to YYYY-MM-DD format, so I can insert it into a MySQL database. I do not get any error, but the date inserted into my db is wrong and the same for every row...

 String date = Sat Mar 04 09:54:20 EET 2017;
 SimpleDateFormat formatnow = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy"); 
 SimpleDateFormat formatneeded=new SimpleDateFormat("YYYY-MM-DD");

 java.util.Date date1 = (java.util.Date)formatnow.parse(date);
 String date2 = formatneeded.format(date1);
 java.util.Date date3= (java.util.Date)formatneeded.parse(date2);


 java.sql.Date sqlDate = new java.sql.Date( date3.getTime() );
 pst.setDate(1, sqlDate);

Solution 1:

    LocalDate date4 = ZonedDateTime
            .parse(date, DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH))
            .toLocalDate();
    java.sql.Date date5 = java.sql.Date.valueOf(date4);

I am using the modern classes in the java.time package. You notice that the code is not only simpler, once you get acquainted with the fluent writing style of the newer classes, it is also clearer.

If you wanted to be 100 % modern, you should also check out whether your latest MySQL JDBC driver wouldn’t accept a LocalDate directly without conversion to java.sql.Date. It should.

A few details to note

  • If you need your code to run on computers outside your control, always give locale to your formatter, or your date string cannot be parsed on a computer with a non-English-speaking locale. You may use Locale.ROOT for a locale neutral locale (it speaks English).
  • If you can, avoid the three letter time zone abbreviations. Many are ambiguous. EET is really only half a time zone since some places where it’s used are on EEST (summer time) now. Better to use either a long time zone ID like Europe/Bucharest or an offset from UTC like +02:00.

These points are valid no matter if you use DateTimeFormatter or SimpleDateFormat.

If you cannot or do not want to move on to the recommended newer classes, the fix to your code is:

    SimpleDateFormat formatnow 
            = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH); 
    SimpleDateFormat formatneeded = new SimpleDateFormat("yyyy-MM-dd");

I am using lowercase zzz since this is documented to match a three-letter time zone name, I know that uppercase ZZZ works too. I have added locale. And maybe most importantly, in the needed format I have changed YYYY (week-based year) to yyyy (calendar year) and DD (day of year) to dd (day of month). All those letters are in the documentation.