28

Before writing a Java Date to an SQL TIMESTAMP column, does JDBC translate the date from the Java virtual machine time zone to that of the database session?

For example, suppose the Java virtual machine time zone is UTC and the database session time zone is UTC-5. If a Java program attempts to store 2000-01-01 00:00:00 by passing it to PreparedStatement#setTimestamp(int, Timestamp), according to the JDBC standard, will the database store TIMESTAMP '2000-01-01 00:00:00' or TIMESTAMP '1999-12-31 19:00:00'?

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • 2
    Timezones are (or should be) only relevant for presentation of dates, not for storage. So no translation should occur. However this is surmise, not an answer. – RedGrittyBrick Nov 08 '10 at 11:56
  • So RedGrittyBrick, you expect the database to store `TIMESTAMP '2000-01-01 00:00:00'`? – Derek Mahar Nov 08 '10 at 12:12
  • RedGrittyBrick, time zone is relevant for dates if you store the time zone. An SQL TIMESTAMP column doesn't store the time zone, though, so it makes sense to store dates independent of location (that is, relative to the UTC time zone). – Derek Mahar Nov 08 '10 at 14:56
  • 1
    RedGrittyBrick, the main issue that I'm trying to understand is how, if at all, the JDBC standard requires a JDBC driver implementation to apply a time zone to a date when it transfers the date between the JDBC client and the database server. – Derek Mahar Nov 08 '10 at 15:12
  • Also see: http://stackoverflow.com/questions/2858182/preparedstatement-and-settimestamp-in-oracle-jdbc – sleske Feb 07 '12 at 10:46

4 Answers4

16

No, JDBC is just an API on how the client can access the database. For timestamp storage, this will have to be dependent by the organisation that writes their database drivers that conforms to the JDBC API standard.

Here's an implementation of MySQL's implementation of PreparedStatement. They seem to take Java's JVM timezone to MySQL Timezone (check the setTimestampInternal() method).

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • 2
    Yes, you are right. It's quite clear from the MySQL JDBC driver implementation that `setTimestampInternal()` translates the given date to the server time zone (`x = TimeUtil.changeTimezone(this.connection, x, tz, 2059 this.connection.getServerTimezone());`). It also formats the date to a string using `SimpleDateFormat` which is locale dependent. – Derek Mahar Nov 08 '10 at 15:19
  • 5
    By contrast, the PostgresQL JDBC driver implementation of `setTimestamp()` translates the given date using the JVM time zone. See methods `AbstractJdbc2Statement#setTimestamp(int, Timestamp, Calendar)` at http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java?rev=1.118&content-type=text/x-cvsweb-markup and `TimestampUtils#toString(Calendar, Timestamp)` at http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2/TimestampUtils.java?rev=1.23&content-type=text/x-cvsweb-markup. Time zone handling is JDBC driver dependent! – Derek Mahar Nov 09 '10 at 16:20
  • @Derek Mahar, that's what I said. The implementation of the API varies per organisation writing the JDBC driver. You shouldn't take it as an absolute that if MySQL (example) converts timezones before storing, SQLite (example) would (which they don't at all). – Buhake Sindi Nov 09 '10 at 20:17
  • Elite, I was confirming what you said with my example of the PostgreSQL JDBC driver. I was trying to express that I agreed with you, but ran out of characters in the comment box, so my final sentence may have come across as disagreement. However, what I really wanted to say was, "So, you are right, time zone handling is JDBC driver dependent!" – Derek Mahar Nov 10 '10 at 15:04
  • Ok....sorry for misunderstanding your statement. Don't forget to accept answers that helped you. :) – Buhake Sindi Nov 10 '10 at 16:02
  • @Buhake Sindi Could you please comment on how ORACLE PreparedStatement works ?? – Kanagavelu Sugumar Dec 28 '12 at 11:06
  • @Kanagavelu Sugumar, why? What do you want to know exactly? – Buhake Sindi Dec 28 '12 at 11:49
  • @Buhake Sindi Please answer me http://stackoverflow.com/questions/14070572/is-java-sql-timestamp-timezone-specific – Kanagavelu Sugumar Dec 28 '12 at 14:28
  • SQL Server get `datetime` field as day since 1900 and milliseconds in day and set that to local `Calendar(1900, 0, dayN)`, if you want to work with UTC - you need to `TimeZone.setDefault(TimeZone.getTimeZone("GMT+00:00"));` before driver loading, see http://stackoverflow.com/a/29705750/173149 – gavenkoa Apr 20 '15 at 17:00
7

Now my requirement is that it should store the value in GMT/UTC irrespective of the timezone of the JVM. Is there a way to set the timezone on the fly and then to unset it once I'm done with JDBC?

Edit: Ok, I found a way around that issue. Did the following

TimeZone default = TimeZone.getDefault();
try
{
  TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

  //Do stuff with JDBC
}
finally
{
  TimeZone.setDefault(default);
}
Jagat
  • 1,392
  • 2
  • 15
  • 25
  • 5
    This might lead to a race condition in case other threads make computations at the same time on dates, assuming the default timezone is not UTC. – Random42 May 21 '14 at 14:28
  • 6
    **BEWARE** [Changing the default](http://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#setDefault-java.util.TimeZone-) time zone is risky business. This change *affects all code in all threads* running in this JVM, not just the local code in your method. – Basil Bourque May 23 '14 at 05:57
2

You can use overloaded setTimestamp setter accepting Calendar instance to specify timezone

Sample (If you're using Joda datetime):

org.joda.time.DateTime sendDateUTC = new DateTime( DateTimeZone.UTC ).withMillis( millis );
statement.setTimestamp (1, sendDateUTC, sendDateUTC.toGregorianCalendar() );

As per javaDoc: Sets the designated parameter to the given java.sql.Timestamp value, using the given Calendar object. The driver uses the Calendar object to construct an SQL TIMESTAMP value, which the driver then sends to the database. With a Calendar object, the driver can calculate the timestamp taking into account a custom timezone. If no Calendar object is specified, the driver uses the default timezone, which is that of the virtual machine running the application.

void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
    throws SQLException;
Cezar
  • 55,636
  • 19
  • 86
  • 87
-1

The spec is goofy. The java.util.Date stores milliseconds from epoch in the GMT reference frame. Java.sql.Timestamp is a Date plus nanoseconds in the same reference frame. All the non-deprecated getters and setters use the GMT reference frame. For any sort of sanity, the default time zone for a storing a Timestamp should be GMT.

In a multi-tiered application, the front-end, the driver, and the database server could all be in different time zones. Some of the tiers could be in different time zones at the same time; for instance, if you are doing internet load-balancing across a continent, or if you have a mobile app connecting to a central server. A cloud operating environment would be much the same scenario where you have no idea where the JDBC driver will be running, nor any guarantee that will never change.

The only way I know to achieve consistency in these environments is to only use the parameter setter and ResultSet getter that accept a Calendar, and make sure every app that accesses the data uses the some calender, preferrably GMT or UTC.

ChrisG65
  • 59
  • 2
  • Chris, I'm not sure you answered Derek's question. Will jdbc adjust the timestamp based on timezone difference between client and server? I'm pretty sure the answer is no. – Andreas May 22 '14 at 18:57
  • 1
    Yes, the answer is still 'no'; at least it should be. I was just explaining the difference between java.sql.Date and java.Util.Date because the original poster did not distinguish which they were talking about. Also, there is no guarantee that all JDBC drivers behave the same way because some actually embed the timezone information into their internal types, and some attach to backends that do not have this capability. Specifying the Calendar reduces the uncertainty. Otherwise, if your backend does not retain timezone, and your clients exist in more than one timezone, what do the values mean? – ChrisG65 Apr 23 '18 at 17:34