Я понимаю, что подобные вопросы были заданы здесь раньше. Но мне все еще нужно было немного больше испытать для моего случая использования - и я немного удивлен/смущен результатом.
Ниже приведено описание (с кодом) теста и результатов.
Я работаю над приложением, которое:
Поэтому очень важно четкое понимание временных данных.
Я пытаюсь понять типы timestamp в MySQL (datetime и timestamp) и как они взаимодействуют с Java-кодом и timestrings ISO8601.
Я прочитал документы MySQL по типу Timestamp - как он преобразует значение времени, чтобы сохранить его как UTC и, при извлечении, преобразует это значение UTC в зону времени сервера или сеанса. Это звучало как хорошее хранилище "точка-в-времени".
Тип MySQL datetime немного более непрозрачен. Эта статья (http://code.openark.org/blog/mysql/timestamp-vs-datetime-which-should-i-be-using) считает, что она не так сильно отличается от строки. Я повторил "SELECT NOW() + 0;" запрос и получил тот же ответ, что и статья.
Чтобы попытаться прояснить ситуацию, я написал небольшой класс Java, который написал одну таблицу базы данных, состоящую из 3 столбцов:
Код Java находится здесь: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d
Я создал 3 разных строчки timestamp ISO8601 - все в один и тот же момент времени - но с разными смещениями/часовыми поясами. Каждый из них был записан в базу данных, извлечен и распечатан.
Для начала я установил часовой пояс сервера базы данных MySQL на "+00: 00".
Выход
Время написания базы данных.
UTC
2018-04-13T11:12:00Z, 1523617920
Europe/Amsterdam
2018-04-13T13:12:00+02:00, 1523617920
Asia/Calcutta
2018-04-13T16:42:00+05:30, 1523617920
Чтение сохраненных времен из базы данных.
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523617920, 2018-04-13T11:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta]
Все выглядит хорошо. Эпоха секунд, когда вставляется что-то вроде https://www.epochconverter.com/, согласуется со строками времени ISO8601.
Затем я изменил часовой пояс сервера MySQL с UTC (+00: 00) в Европу/Амстердам (+02: 00) и снова прочитал сохраненные моменты.
Выход
Чтение сохраненных времен из базы данных.
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523625120, 2018-04-13T13:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523625120, 2018-04-13T15:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523625120, 2018-04-13T18:42+05:30[Asia/Calcutta]
Я ожидал, что столбец Datetime будет затронут - считая, что он не хранит информацию о часовом поясе. Тем не менее, это была колонка Timestamp, которая перемещалась.
Мы не будем регулярно менять часовой пояс сервера. Я пытаюсь понять, какой тип данных MySQL лучше всего представляет собой момент времени - что-то, на что я могу рассчитывать, как точное и неизменное (а не разрушение головы). Исходя из вышесказанного, если я предоставляю информацию "точно в срок" в форме строки ISO8601, тип MySQL Datetime сохраняет предоставленную информацию.
Совершенно возможно, что мой тестовый код неверен и/или моя интерпретация результатов. Мог бы сделать с небольшим руководством здесь.
В приведенном выше тестовом примере тип Datetime MySQL лучше справляется с хранением информации о времени?
После немного более тонкой настройки я получил класс Java, который управляет хранением и получением информации о времени. Я все еще немного нервничаю по этому поводу - так много частей хотят сказать, что время, и это делает меня неудобным.
Класс находится в оригинальной форме: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d (и изменения показывают изменения).
Timestamp Тип MySQL - это метка времени. Мне не нужно возиться с этим.
Datetime Тип MySQL Я все еще немного смущен (я не знаю, что это такое), но зная часовой пояс, я могу поддерживать информацию о времени.
Не совсем до того, чтобы полностью проанализировать это. Не весело, пытаясь понять это.
time_zone
сеанса MySQL не соответствует JVM-Duser.timezone
. С MySQL Connector / J, различные (на первый взгляд причудливые) поведения зависят от настроекuseJDBCCompliantTimezoneShift
,useLegacyDatetimeCode
иserverTimezone
И от обнаружения типов данных MySQL и сопоставления с типами данных JDBC ... строки и целые числа могут проходить через невредимые JB, но типы могут быть обмануты.