Dates with no time or timezone component in Java/MySQL

java.time

This was indeed a problem with java.util date-time API until JSR-310 was incorporated in Java SE 8. The java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as “the epoch”, namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM’s timezone, calculated from this milliseconds value.

The problem that you have described was addressed with the modern date-time API* where we have LocalDate that represents just a date. In the following sentence, the Oracle tutorial describes its purpose nicely:

For example, you might use a LocalDate object to represent a birth
date, because most people observe their birthday on the same day,
whether they are in their birth city or across the globe on the other
side of the international date line.

A couple of pages later, it describes it again as follows:

A LocalDate represents a year-month-day in the ISO calendar and is
useful for representing a date without a time. You might use a
LocalDate to track a significant event, such as a birth date or
wedding date.

Which datatype should I use for LocalDate?

It maps with DATE ANSI SQL type. The mapping of ANSI SQL types with java.time types have been depicted as follows in this Oracle’s article:

ANSI SQL Java SE 8
DATE LocalDate
TIME LocalTime
TIMESTAMP LocalDateTime
TIME WITH TIMEZONE OffsetTime
TIMESTAMP WITH TIMEZONE OffsetDateTime

How to use it in JDBC?

Given below is a sample code to insert a LocalDate into columnfoo (which is of DATE type):

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

Given below is a sample code to retrieve a LocalDate from columnfoo:

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
    // Assuming the column index of columnfoo is 1
    LocalDate localDate = rs.getObject(1, LocalDate.class));
    System.out.println(localDate);
}
rs.close();
st.close();

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


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Leave a Comment