Java : Ошибка перехода на летнее время с временной меткой Mysql

#java #mysql #datetime #timestamp

Вопрос:

У меня есть определенная таблица в mysql с полем refresh_time Type as timestamp .

В моем коде я обновляю refresh_time поле до будущей даты следующего месяца. Для этого я рассчитываю миллисекунды на дату следующего месяца, используя следующую логику :

 periodRefresh = currentTime   MyServiceUtils.calculateNoOfDaysInMonth(currentTime)*86400000L;
 

А затем значение periodRefresh (milliseconds) , в которое я преобразую java.sql.Timestamp и передаю его на сторону бд, чтобы удалить поле :

 new Timestamp(periodRefresh);
 

Но произошло то, что текущая дата в бд была 2021-04-03 15:57:13 , и когда была запущена вышеуказанная логика для обновления времени до следующего месяца, в то же время, она обновила время, 2021-05-03 13:57:13 которое на 2 часа меньше, чем ожидалось.

Наш сервер следует часовому поясу UTC, но я вижу, что пользователь был из Австралии, и в тот день (4 апреля 2021 года) в AEST было летнее время. Но даже в этом случае это не добавляет к вышесказанному, как если бы я перешел 2021-04-03 15:57:13 UTC на AEST, это происходит так же, как 2021-04-03 01:57:13 и переход на летнее время в 3 часа ночи.

Все вышесказанное немного смутило меня следующими вопросами:

  • Если я следую часовым поясам UTC, то также влияет sql.Timestamp и mysql может повлиять летнее время?
  • Как летнее время влияет на моего пользователя в Австралии, когда я следую часовому поясу UTC?
  • Даже если бы влияло летнее время, это должно было увеличить/уменьшить время на 1 час, но как в моем случае произошла разница в 2 часа?

Комментарии:

1. Timestamp ничего не знает о DST или часовых поясах. По сути, это просто число, выражающее смещение от эпохи. Какое бы программное обеспечение ни отображало его, оно будет интерпретировать его в контексте региона и часового пояса, в котором оно просматривается

2. @g00se Итак, когда я проверяю таблицу mysql, время в поле на 2 часа меньше, чем ожидалось. Итак, какова может быть возможная причина этого?

3. mysql имеет внутреннюю логику для экономии дневного света см. dev.mysql.com/doc/refman/8.0/en/time-zone-support.html используйте thqat

4. MyServiceUtils что-то не так? Трудно сказать без информации

5. @g00se Речь идет не о MyServiceUtils, если вы видите, что это просто указывает количество дней. Но здесь ошибка в часах.

Ответ №1:

В MySQL TIMESTAMP типы данных всегда хранятся в таблицах в формате UTC. Когда вы помещаете их в базу данных, она сначала переводит их из time_zone настроек вашего подключения в UTC. И когда вы их извлекаете, это переводит их в другую сторону. Это не относится DATETIME к типам данных.

Такое TIMESTAMP поведение удобно, если у вас есть глобальное приложение. Вы можете запросить у каждого пользователя предпочтительный часовой пояс и сохранить его в качестве параметра пользовательских предпочтений.

Если вы возьмете необработанное значение (секунды с момента эпохи UNIX в UTC) TIMESTAMP и добавите к нему секунды за месяц, полученное значение метки времени может находиться в другом режиме дневного времени. Так что это будет переведено по-другому.

Любой

  1. выполните обработку меток времени в MySQL, например, с помощью
     UPDATE tbl SET periodRefresh = periodRefresh   INTERVAL 1 MONTH;
     
  2. сделайте все это в своем приложении и DATETIME не используйте TIMESTAMP типы данных (чтобы избежать перевода часового пояса базы данных или
  3. сделайте все это в своем приложении и используйте SET time_zone='UTC' ; при каждом подключении.

Комментарии:

1. Под 3-м вариантом вы имели в виду установку time_zone=’UTC’ как @@session.time_zone; ? В качестве часового пояса настройки подключения будет выбрана только временная зона сервера