Two points will make this work much easier:
- Work with date-time objects rather than strings.
You should be using JDBC to extract java.sql.Timestamp objects from your database rather than String representations of those date-time values.
- Use the java.time framework built into Java 8 and later.
Avoid the old java.util.Date/.Calendar classes.
First we must either specify a formatter by which to parse your input string, or alter it to meet the ISO 8601 standard used by default in java.time. The ISO 8601 format is close to SQL format, replacing the space in the middle with a T
.
String input = "2016-01-08 08:03:52.0";
String inputIso8601 = input.replace ( " ", "T" );
Parse that string as a local date-time, which means any locality. The input string lacks any time zone or offset-from-UTC info, so we start with a local and will apply an assumed time zone afterwards.
LocalDateTime localDateTime = LocalDateTime.parse ( inputIso8601 );
Let's apply the assumed time zone. I am arbitrarily choosing Montréal but obviously you need to know and use whatever time zone was intended for that string input. If you are sure that string meant UTC, use the ZoneOffset.UTC
.
ZoneId zoneId = ZoneId.of ( "America/Montreal" ); // Or perhaps ZoneOffset.UTC constant.
ZonedDateTime zdt = ZonedDateTime.of ( localDateTime, zoneId );
Now we are ready to convert to a java.sql.Timestamp
object, to be sent to the database. That old class has a new method, for converting to/from java.time objects. The conversion requires an Instant
object which is a moment on the timeline in UTC. We can extract an Instant
from our ZonedDateTime
.
Instant instant = zdt.toInstant ( );
java.sql.Timestamp ts = java.sql.Timestamp.from ( instant );
Dump to console.
System.out.println ( "input: " + input + " in ISO 8601: " + inputIso8601 + " is localDateTime: " + localDateTime + " in zoneId: " + zoneId + " is zdt: " + zdt + " gives instant: " + instant + " which converts to java.sql.Timestamp ts: " + ts );
input: 2016-01-08 08:03:52.0 in ISO 8601: 2016-01-08T08:03:52.0 is localDateTime: 2016-01-08T08:03:52 in zoneId: America/Montreal is zdt: 2016-01-08T08:03:52-05:00[America/Montreal] gives instant: 2016-01-08T13:03:52Z which converts to java.sql.Timestamp ts: 2016-01-08 05:03:52.0
Read that console output carefully. Note the time-of-day on ts
. This shows the unfortunate behavior of the java.sql.Timestamp
method toString
to silently apply the JVM’s current default time zone when generating the textual representation of the date-time value. My JVM here had a default time zone of America/Los_Angeles
. So the time-of-day was adjusted (confusingly).
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.
With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or 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.