Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert java.time.Instant to java.sql.Timestamp without Zone offset

In the application I am developing, I need to convert java.time.Instant object to java.sql.Timestamp. When I create Instant object like:

Instant now = Instant.now(); 

I receive something like 2017-03-13T14:28:59.970Z. And when I try to create Timestamp object like this:

Timestamp current = Timestamp.from(now); 

I receive something like 2017-03-13T16:28:59.970Z. The same result but with an additional 2 hour delay. Can someone explain why this is happening and provide me with an answer to fix this problem without this delay?

When I created like this:

LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC); Timestamp current = Timestamp.valueOf(ldt); 

Everything works well, but I try to avoid conversions. Is there a way to do this by only using Instant object?

like image 243
Aleydin Karaimin Avatar asked Mar 13 '17 14:03

Aleydin Karaimin


People also ask

How do I convert instant Timestamp?

We can use Timestamp. from() to convert Instants into Timestamps: Instant instant = Instant. now(); Timestamp timestamp = Timestamp.

Does Java sql Timestamp have timezone?

getTimestamp call has no Calendar parameter, or the Calendar parameter value is null, the IBM Data Server Driver for JDBC and SQLJ uses the default time zone when it constructs the returned object.

Is Java Instant always UTC?

Instant objects are by default in UTC time zone. Printing the value of timestamp gives us 2016-11-29T14:23:25.551Z . 'Z' here denotes the UTC+00:00 time zone.


1 Answers

I changed my computer’s time zone to Europe/Bucharest for an experiment. This is UTC + 2 hours like your time zone.

Now when I copy your code I get a result similar to yours:

    Instant now = Instant.now();     System.out.println(now); // prints 2017-03-14T06:16:32.621Z     Timestamp current = Timestamp.from(now);     System.out.println(current); // 2017-03-14 08:16:32.621 

Output is given in comments. However, I go on:

    DateFormat df = DateFormat.getDateTimeInstance();     df.setTimeZone(TimeZone.getTimeZone("UTC"));     // the following prints: Timestamp in UTC: 14-03-2017 06:16:32     System.out.println("Timestamp in UTC: " + df.format(current)); 

Now you can see that the Timestamp really agrees with the Instant we started out from (only the milliseconds are not printed, but I trust they are in there too). So you have done everything correctly and only got confused because when we printed the Timestamp we were implicitly calling its toString method, and this method in turn grabs the computer’s time zone setting and displays the time in this zone. Only because of this, the displays are different.

The other thing you attempted, using LocalDateTime, appears to work, but it really does not give you what you want:

    LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC);     System.out.println(ldt); // 2017-03-14T06:16:32.819     current = Timestamp.valueOf(ldt);     System.out.println(current); // 2017-03-14 06:16:32.819     System.out.println("Timestamp in UTC: " + df.format(current)); // 14-03-2017 04:16:32 

Now when we print the Timestamp using our UTC DateFormat, we can see that it is 2 hours too early, 04:16:32 UTC when the Instant is 06:16:32 UTC. So this method is deceiving, it looks like it’s working, but it doesn’t.

This shows the trouble that lead to the design of the Java 8 date and time classes to replace the old ones. So the real and good solution to your problem would probably be to get yourself a JDBC 4.2 driver that can accept an Instant object readily so you can avoid converting to Timestamp altogether. I don’t know if that’s available for you just yet, but I’m convinced it will be.

like image 89
Ole V.V. Avatar answered Sep 23 '22 19:09

Ole V.V.