Amro Younes Amro Younes - 2 months ago 9
Java Question

Convert Datetime and timestamp in mysql from default timezone to UTC in Java is not working when I try to set it at time of connection

The mysql db that I am using is configured as such:

mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM | SYSTEM |
+--------------------+---------------------+


The centos machines the database is running on is using PST.

I have a table with different time objects that I want to make sure that when i read them in my program they are in UTC time.

describe mytable:

| start_date | timestamp | NO | MUL | CURRENT_TIMESTAMP |
| update_date | datetime | YES | MUL | NULL |

select start_date, update_date from mytable limit 1;

+---------------------+---------------------+
| start_date | update_date |
+---------------------+---------------------+
| 2015-11-02 07:42:15 | 2015-11-02 07:48:40 |
+---------------------+---------------------+


The above times are in PST.

In Java, I connect to the DB as such:

String dbStr = String.format("jdbc:mysql://%s:%d/%s", sqlHost, sqlPort, sqlDb);

Properties connectionProps = new Properties();
connectionProps.put("user", USER);
connectionProps.put("password", PASSWORD);
connectionProps.put("useLegacyDatetimeCode", "false");
connectionProps.put("serverTimezone", "UTC");


However, when I read the dates using the query above, they still come out as PST. I could convert the dates later on in Java when I extract the columns, but is there a way to do this at connection time. I did this in Python by modifying the cursor timezone, however, in Java I would have to use PrepareStatement instead of Statement to even achieve this.

I am using mysql-connector-java-5.1.36. I have had a similar issue in the past when I was trying to enforce an encoding change from latin to UTF-8 and I never got it to work at the connection level. Again, in python I was able to achieve this but not in Java.

I thought it might be related to this syntax and hence why I changed from

String.format("jdbc:mysql://%s:%d/%s?useLegacyDatetimeCode=false&serverTimezone=UTC", sqlHost, sqlPort, sqlDb)


to using properties.

What I suspect is the issue and I could not find evidence on how to remedy that is telling my connection that hey, the server is storing dates in PDT, but when you give me the info I want it in UTC.

Thanks...Amro

It turns out the root cause of the issue is that the select statement was converting the date objects to string within the query:

SELECT date_format(start_date, '%Y-%m-%dT%H:%i:%s'),
date_format(update_date, '%Y-%m-%dT%H:%i:%s') from myTable;


If you remove the date_format and preserve the date object, the timezone conversions take place. You can then format the date objects as strings as you see fit. However, be ware of the timezone your JVM is running in as the conversion takes that into account. The connection to the DB with the TZ setup tells your program what TZ the data in the DB is in. The TZ your JVM is running in will determine how to convert the date/time from the db into your program. You can pass a parameter to the JVM or set the default TZ to ensure your JVM is agnostic to the environment it is running in.

Answer

It turns out the root cause of the issue is that the select statement was converting the date objects to string within the query:

SELECT date_format(start_date, '%Y-%m-%dT%H:%i:%s'), 
       date_format(update_date, '%Y-%m-%dT%H:%i:%s') from myTable;

If you remove the date_format and preserve the date object, the timezone conversions take place. You can then format the date objects as strings as you see fit. However, be ware of the timezone your JVM is running in as the conversion takes that into account. The connection to the DB with the TZ setup tells your program what TZ the data in the DB is in. The TZ your JVM is running in will determine how to convert the date/time from the db into your program. You can pass a parameter to the JVM or set the default TZ to ensure your JVM is agnostic to the environment it is running in.

Comments