java.time
Use java.time classes, built into Java 8 and later. Never use the terrible legacy date-time classes such as Date
, Calendar
, SimpleDateFormat
, GregorianCalendar
, and Timestamp
.
As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.
String input = "2014-11-10 04:05:06.999999".replace( " " , "T" ) ; // Convert from SQL style to ISO 8601 standard format where `T` separates the year-month-day portion from hour-minute-second portion.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
Not a moment
Be aware that a LocalDateTime
is not a moment, is not a point on the timeline. Your input lacks the context of a time zone or offset-from-UTC. So we do not know if your mean 4 AM on the 10th in Tokyo Japan, 4 AM in Toulouse France, or 4 AM in Toledo Ohio US — three very different moments, several hours apart on the timeline.
So you would be storing the LocalDateTime
object’s value in a Postgres database column of type TIMESTAMP WITHOUT TIME ZONE
.
A moment
If your intent was to represent a moment, a specific point on the timeline, you most know for certain the intended time zone.
Let's say you know the 4 AM was meant to be in Tokyo Japan time zone. Apply a ZoneId
to the LocalDateTime
to get a ZonedDateTime
object.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Unfortunately, the JDBC 4.2 spec does not require support for the two most commonly used types, Instant
and ZonedDateTime
. No matter, we can easily convert to OffsetDateTime
, for which support is required by JDBC spec.
OffsetDateTime odt = zdt.toOffsetDateTime() ;
Such a value, a specific point on the timeline, should be written to a database column of type TIMESTAMP WITH TIME ZONE
.
Write to the database.
myPreparedStatement.setObject( … , odt ) ;
And retrieval.
myResultSet.getObject( … , OffsetDateTime.class ) ;
java.sql.Timestamp
If you cannot move to Java 8, then you should be using your JDBC driver to get a java.sql.Timestamp
object. That class is a hack, but it works. It is a java.util.Date but tracks the fractional seconds to resolution of nanoseconds instead of milliseconds. So it will preserve the microseconds used by Postgres.
You can use it as a java.util.Date but in other contexts you'll lose your extra resolution.
But are you really stuck with Java 6, 7, or earlier in the year 2020 now? Best to move to either Java 8 or Java 11, the two LTS versions.
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. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?