tl;dr
For database column of type TIMESTAMP WITHOUT TIME ZONE
.
myPreparedStatement // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject( // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
… , // Fill-in to indicate which placeholder in SQL statement.
LocalDateTime.of( // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
LocalDate.parse( "2018-01-23" ) , // Parse the date-only value.
LocalTime.parse( "21:54" ) // Parse the time-of-day.
) // Returns a `LocalDateTime` object.
)
For database column of type TIMESTAMP WITH TIME ZONE
.
myPreparedStatement // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject( // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
… , // Fill-in to indicate which placeholder in SQL statement.
LocalDateTime.of( // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
LocalDate.parse( "2018-01-23" ) , // Parse the date-only value.
LocalTime.parse( "21:54" ) // Parse the time-of-day.
) // Returns a `LocalDateTime` object.
.atZone( // Assign a time zone to make a moment.
ZoneId.of( "Pacific/Auckland" ) // Real time zones have a proper name in `Continent/Region` format. Never use 2-4 letter pseudo-zones such as `PDT`, `IST`, `CST`, etc.
) // Returns a `ZonedDateTime` object.
.toOffsetDateTime() // Strip out the time zone, leaving only a mere offset-from-UTC (a number of hours-minutes-seconds). Returns a `OffsetDateTime` object.
.withOffsetSameInstant( // Adjust the offset-from-UTC to UTC itself (an offset of zero). Same moment, different wall-clock time.
ZoneOffset.UTC
) // Returns another `OffsetDateTime` object.
)
java.time
The modern approach uses the java.time classes that years ago supplanted the terrible old legacy classes (Calendar
, Date
, SimpleDateFormat
, etc.).
LocalDate
The LocalDate
class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
The common SQL format for a date-only value in text is YYYY-MM-DD. This is also the format defined by the ISO 8601 standard. The java.time classes use the ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.
LocalDate ld = LocalDate.parse( "2018-01-23" ) ;
Similar for a string in format of HH:MM for hours and minutes of a time-of-day.
LocalTime lt = LocalTime.parse( "21:54" ) ;
Combine the date with the time.
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
ldt.toString(): 2018-01-23T21:54
Be aware that a LocalDateTime
, purposely lacking any concept of time zone or offset-from-UTC, is not a moment, is not a point on the timeline. As such, it is only appropriate to save to a database in a column of a data type akin to the SQL-standard TIMESTAMP WITHOUT TIME ZONE
.
JDBC 4.2
As of JDBC 4.2, we can directly exchange java.time objects with the database via setObject
& getObject
.
myPreparedStatement.setObject( … , ldt ) ;
Retrieval.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
ZonedDateTime
If you want to work with moments, actual points on the timeline, use the appropriate Java classes (Instant
, OffsetDateTime
, ZonedDateTime
).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
OffsetDateTime
Now we have a moment at hand. Usually best to focus on UTC when moving dates around such as transferring to a database.
OffsetDateTime odtUtc = zdt.toOffsetDateTime().withOffset( ZoneOffset.UTC ) ;
Send to database.
myPreparedStatement.setObject( … , odtUtc ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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.