2013-03-04 2 views
3

Я хотел бы сохранить временную метку в базе данных, не будучи преобразованной в локальный часовой пояс драйвером jdbc. В настоящее время для меня важны только MySQL и PostgreSQL, но я был бы признателен, если есть независимое от базы данных решение.JDBC/MySQL: сохранить временную метку всегда с помощью UTC

Пример:

// i want that to be saved as 1970-01-01 00:00:00 
TimeStamp ts = new java.sql.Timestamp(0); 

// gets transformed to local time by jdbc driver (in my case to 1970-01-01 01:00:00) 
st.setTimestamp(0, new java.sql.Timestamp(0)); 

// only works using postgres (mysql connector seems to ignore the calendar) 
// postgres => 1970-01-01 00:00:00 
// mysql => 1970-01-01 01:00:0 
Calendar calutc = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 
st.setTimestamp(0, new java.sql.Timestamp(0), utccal); 

Я уже пытался вычислить значение временной метки, которые получают преобразованный к правильному значению (например -3600000 => 1970-01-01 00:00:00 в моей временной зоне) но это не работает на postgres в датах, близких к дневным изменениям экономии времени.

ответ

11

Я нашел решение. У MySQL была ошибка в своем соединителе JDBC, игнорируя предоставленный объект Calendar для setTimestamp/getTimestamp. Они исправили ошибку в версии 5.1.5 соединителя, но старое (неправильное) поведение по-прежнему является поведением по умолчанию. Чтобы использовать правильный код, вы должны передать параметр «useLegacyDatetimeCode = false» в URL-адрес соединителя.

Дополнительная информация: http://bugs.mysql.com/bug.php?id=15604

+1

Я использовал '& serverTimezone = UTC & useLegacyDatetimeCode = false' с успехом, без драйвера serverTimezone jdbc жаловался на неправильный часовой пояс. – snowindy

+1

Полный URL-адрес, для справки: jdbc: mysql: // localhost: 3306/pm_func? CharacterEncoding = UTF-8 & useEncoding = true & autoReconnect = true & serverTimezone = UTC & useLegacyDatetimeCode = false – snowindy

0

Дата и временная метка в Java не зависят от часовой пояс. Новая отметка времени (0) действительно соответствует 1970-01-01 00:00:00 в UTC. Вы должны использовать SimpleDateFormat и установить желаемый часовой пояс на нем, чтобы визуально проверить ваши даты. Вычитание длинной константы из метки времени, чтобы сделать ее «правильной», когда распечатка с использованием System.out.println очень не правильная.

При использовании базы данных у вас есть выбор типов данных для даты/времени/метки времени. Некоторые из них поддерживают информацию о часовом поясе, а некоторые - нет. Если вы решите использовать обработку часовых поясов в своей базе данных, вы должны изучить ее в деталях. Если вы хотите обойти это, у вас есть возможность хранить даты/время/временные метки в базе данных в виде строк и делать все форматирование в вашем Java-коде.

+0

Насколько я знаю, поддерживает только JDBC setTimestamp для значений даты и времени (SETDATE только дата), который делает преобразование часового пояса. Я считаю, что правильным решением является setTimestamp с атрибутом Calendar. Я нашел атрибут MySQL Connector «useLegacyDatetimeCode = false», который кажется enalbe совместимым с jdbc поведением для MySQL (@MySQL: wtf?) – Werzi2001

+0

PostgreSQL имеет несколько типов даты/времени: временная метка с часовым поясом, временная метка без часового пояса, дата, время с часовой пояс, время без часовой пояс. Уверен, что у MySQL одинаковое разнообразие типов. К сожалению, я считаю, что эти типы не стандартизированы, поэтому разные базы данных имеют похожие, но не идентичные наборы типов даты и времени. – Olaf

+0

Да, это правда. Но проблема заключается в том, чтобы сообщить драйверу jdbc, какой часовой пояс он должен использовать, чтобы сохранить метку времени. По умолчанию используется локальный часовой пояс, но я хочу, чтобы utc использовался. Поэтому существует параметр Calendar to getTimestamp/setTimestamp, который по умолчанию игнорируется MySQL. См. Мой собственный ответ для деталей. – Werzi2001

Смежные вопросы