Is this the correct way to get java.sql.Timestamp in UTC from a date?

I am developing a SonarQube plugin, and for one of my needs I need to save the project analysis date as SQL TIMESTAMP ( Note: a TIMESTAMP , not TIMESTAMP WITH TIMEZONE ).

Here's how I do it now:

 // In the SonarQube Sensor // .getAnalysisDate() returns a java.util.Date final Instant instant = module.getAnalysisDate().toInstant(); // Timestamp at UTC from the Instant final LocalDateTime dt = LocalDateTime.frominstant(instant, ZoneOffset.UTC); final Timestampt ts = Timestamp.valueOf(dt); 

I have a little problem understanding the concept of Instant, there is also ZonedDateTime, etc.

Anyway, this looks like what I want, but is it right?

+6
source share
3 answers

To save UTC TIMESTAMP in your database, you need to create a Java TIMESTAMP that represents the date of your report (for example, November 8, 7pm UTC), but in the local time zone without conversion (for example, November 8, 7pm CET). So, your approach is correct: get the LocalDateTime the analysis date in UTC (November 8, 7 pm) and create a timestamp in your local time zone on LocalDateTime .

I don't think there is a shorter / better way to do this. If you used the sql field TIMESTAMP WITH TIME ZONE , you would not have to do any manipulations, and Date.from(Instant) correct result.


Clarification of the concepts under consideration using the time at which you sent your question as an example (Sunday, November 8, 2015, at 7 pm UTC) and provided that your local time zone is CET (Central European Time = UTC + 1):

  • Java TIMESTAMP will be the number of milliseconds from an era, i.e. represents a unique moment in the time line on which you posted your question and does not have information about the time zone.
  • when you save this TIMESTAMP in the TIMESTAMP field (i.e. without a time zone), the jdbc driver will calculate the date / time corresponding to your TIMESTAMP in the default time zone (if Calendar not provided) - so your database will show Sunday November 8 at 8 in the evening.
  • a java.time.Instant is similar to Java TIMESTAMP : it represents a unique point in time without time zone information
  • a LocalDateTime is similar to sql TIMESTAMP , it says, for example, Sunday, November 8, 8 pm, but you do not know what time point is missing without additional information about the time zone.
  • a ZonedDateTime is essentially a LocalDateTime + time zone. For example, Sunday, November 8, 8 pm [Europe / Paris], which usually identifies a unique moment, but not necessarily (think when the clock changes back for DST and the same hour is repeated twice).
  • a OffsetDateTime is essentially a LocalDateTime + offset versus UTC. For example, Sunday, November 8th, 8pm + 01:00. This defines a unique point in time.

The standard approach usually is to store the moment as sql TIMESTAMP WITH TIME ZONE and use either TIMESTAMP or OffsetDateTime on the Java side.

+4
source

Timestamp.from(instant) is all you need.

Neither java.time.Instant nor java.time.Instant have a time zone, so you do not need to convert to UTC.

Alternatively directly from java.util.Date

 long millisSinceEpoch = module.getAnalysisDate().getTime(); Timestamp timestamp = new Timestamp(time); 
+2
source

If performance matters, I would use the following:

 final long timeAtLocal = module.getAnalysisDate(); // or System.currentTimeMillis(); or new Date().getTime(); etc. final long offset = TimeZone.getDefault().getOffset(timeAtLocal); final Timestamp timeAtUTC = new Timestamp(timeAtLocal - offset); 
0
source

All Articles