-1

I have a column in my table of Date type in MYSQL and inserting the date format of 25-March-2019 hh:mm:ss returns an error telling me incorrect data value.

So I have my code written like this:

 String startdt=request.getParameter("startdate");
    String enddate=request.getParameter("enddate");
    SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
    Date Startdate=dateFormat.parse(startdt);
    Date Enddate=dateFormat.parse(enddate);

And I am passing Startdate and Enddate to a function that inserts into my table column.

Is there a way I can have Startdate and Enddate above just return in yyyy-mm-dd without the time so I can insert to my db without error?

halfer
  • 19,824
  • 17
  • 99
  • 186
Daredevil
  • 1,672
  • 3
  • 18
  • 47
  • 3
    Why are you using string formatting at all instead of using a `Date` or `Instant` object directly? – chrylis -cautiouslyoptimistic- Mar 26 '19 at 03:28
  • Because I am getting the value from a html page so it needs to get in string. – Daredevil Mar 26 '19 at 03:30
  • 1
    You *really* need to show how you're handling the SQL. This smells like you have injection attacks. (Additionally, while it may be unavoidable in your specific case if you're manually parsing parameters from an `HttpServletRequest` you're Doing It Wrong™, as all major frameworks will do this for you.) – chrylis -cautiouslyoptimistic- Mar 26 '19 at 03:31
  • The time component you see is a relic of how `Date` works internally (it stores a `long` which represents time as an offset from epoch). The new classes in `java.time` work differently, but don't play well with JDBC. – Elliott Frisch Mar 26 '19 at 03:33
  • @ElliottFrisch Depends on the JDBC driver. Postgres is okay, but I can't speak for MySQL. – chrylis -cautiouslyoptimistic- Mar 26 '19 at 03:53
  • Why does specifying dateFormat to `yyyy-mm-dd` still returns the time as well? – Daredevil Mar 26 '19 at 03:54
  • 1
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalDate` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). You may not need an explicit formatter. And you certainly don’t need to format your `LocalDate` before handing it over to MySQL. – Ole V.V. Mar 26 '19 at 08:08
  • 1
    @OleV.V. Yea `LocalDate` is probably the latest library that most people would suggest but unfortunately,it only works for Java 8 and above. – Daredevil Mar 26 '19 at 08:10
  • Which Java version are you using? `LocalDate` and java.time have been backported, so they work on Java 6 and 7 too. Only unfortunately on those Java versions you will need to convert to the old-fashioned `java.sql.Date` before handing to MySQL. In any case here’s the link to the backport: [ThreeTen Backport](https://www.threeten.org/threetenbp/). – Ole V.V. Mar 26 '19 at 08:14
  • I am using Java 7 though. Heard another commenter mentioned ThreeTen Backport but I unfamiliar with it. What does it actually do? I assume it allows me to use java 8 features backporting it to java 7 version? – Daredevil Mar 26 '19 at 08:17
  • 1
    @Daredevil You should have disclosed any constraints, such as being limited to Java 7, in your Question. – Basil Bourque Mar 26 '19 at 16:30

2 Answers2

3

tl;dr

myPreparedStatement
.setObject(
    LocalDate.parse( "2019-01-23" ) 
) ;

DATE in MySQL is date-only

The DATE type in MySQL is a date-only value, without time-of-day and without time zone.

Excerpting from MySQL 8.0 documentation:

The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'.

Use a date-only type in Java for data coming from a date-only type in your database. The java.util.Date class you are trying to use is not a date, it is a moment in UTC, a date with time-of-day and offset-from-UTC of zero, all tracked as a count of milliseconds from the first moment of 1970 in UTC. The misnaming of that class is only the first of many poor design choices made by those programmers. Move on to java.time classes instead. Stop using Date.

MM = month number, not name

Your format of "yyyy-MM-dd" is for a numeric month, not the string of month name shown in your example value of 25-March-2019.

Avoid legacy date-time classes

The SimpleDateFormat and Date classes are terrible, a wretched mess of bad design. They were supplanted years ago with the adoption of JSR 310, implemented in the java.time classes.

Smart objects, not dumb strings

Exchange objects with your database where possible, not text.

As of JDBC 4.2, we can directly exchanged java.time objects with the database. For a date-only value, as with SQL-standard DATE type, use the java.time.LocalDate class.

Apparently, your text inputs for date values is YYYY-MM-DD which is standard ISO 8601 format. The java.time classes use ISO 8601 formats by default. So no need to specify a formatting pattern.

LocalDate localDate = LocalDate.parse( "2019-01-23" ) ;
myPreparedStatement.setObject( … , localDate ) ;

Retrieval.

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

localDate.toString(): 2019-01-23

If you want to produce a string representing the value of that LocalDate object in a different textual format, use the DateTimeFormatter class. Search Stack Overflow for more info as it, like the rest of your Question, has been covered many times already on Stack Overflow. Do search Stack Overflow before posting.

Tip: Generally best to use a PreparedStatement in your JDBC work. One major benefit is thwarting SQL Injection security attacks.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

Java 7 and ThreeTen Backport

    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("d-MMMM-uuuu HH:mm:ss", Locale.ENGLISH);
    String dateFromHtmlForm = "25-March-2019 22:43:55";
    LocalDateTime dateTime = LocalDateTime.parse(dateFromHtmlForm, formatter);
    // We are discarding the time of day and only saving the date
    java.sql.Date dateToSave = DateTimeUtils.toSqlDate(dateTime.toLocalDate());

    String insertSql = "insert into your_table (your_date_column) values (?);";
    try (PreparedStatement insertStatement
            = yourDatabaseConnection.prepareStatement(insertSql)) {
        insertStatement.setDate(1, dateToSave);
        int rowsInserted = insertStatement.executeUpdate();
    }

As has already been said, pass date objects to MySQL, not strings. In Java 8 and later these would have been LocalDate objects, but in Java 7 we will need to make do with the poorly designed java.sql.Date class. It’s still better than strings. And the conversion from LocalDate is straightforward.

On Java 7 we can use java.time through the backport, ThreeTen Backport (ThreeTen for JSR-310). My imports are:

import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.format.DateTimeFormatter;

Why would we want to use an external library for this? There are pros and cons, of course. Advantages include:

  • java.time is so much nicer to work with than the old-fashoined Date and SimpleDateFormat and gives clearer code.
  • It’s future-proof: once you move to Java 8 or later, all you need to do is change your import statements (and discard the library and retest).

Links

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