Как мне заставить мой Spring Boot API возвращать время UTC для значений MySQL Date вместо «2018-08-01T04: 00: 00Z»? - PullRequest
0 голосов
/ 22 января 2019

Как я могу заставить Spring Boot, Java, MyBatis, Jackson и MySQL возвращать время UTC для даты без ее преобразования? Запрос возвращает дату типа

+------------+
| hitDate    |
+------------+
| 2018-04-24 |
+------------+

В классе API есть поле, подобное

@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss'Z'", timezone="UTC")
Date hitDate;

API-вызовы возвращают значения типа

"hitDate":"2018-08-01T04:00:00Z"

Очевидно, что он не может иметь компонент времени. Таким образом, он думает, что дата с 00:00 времени находится в EST (системный часовой пояс -4: 00) и пытается преобразовать ее в UTC, добавив 4 часа. Он работает на производстве, где все настроено на UTC. Мой местный системный часовой пояс установлен на восточное стандартное время. Я пытался

  • &useLegacyDatetimeCode=false&serverTimezone=UTC в соединении MySQL для spring.datasource.url в config/application.properties
  • user.timezone=UTC в config/application.properties
  • SET @@global.time_zone = '+00:00'; в MySQL
  • mvn spring-boot:run -Dexec.args="-Duser.timezone=UTC"

Мой источник данных при инициализации:

DATASOURCE = org.apache.tomcat.jdbc.pool.DataSource@67c7bbdf {ConnectionPool [defaultAutoCommit = null; defaultReadOnly = NULL; defaultTransactionIsolation = -1; defaultCatalog = NULL; driverClassName = com.mysql.jdbc.Driver; maxActive = 100; maxIdle = 100; minIdle = 10; initialSize = 10; maxWait = 30000; testOnBorrow = TRUE; testOnReturn = ложь; timeBetweenEvictionRunsMillis = 5000; numTestsPerEvictionRun = 0; minEvictableIdleTimeMillis = 60000; testWhileIdle = ложь; testOnConnect = ложь; пароль = ********; URL = JDBC: MySQL: // локальный: 3306 / AppDB UseSSL = ложь и useUnicode = да и characterEncoding = UTF-8 & useLegacyDatetimeCode = ложь и serverTimezone = UTC; имя пользователя = корень; validationQuery = / * ping * / SELECT 1; validationQueryTimeout = -1; validatorClassName = NULL; validationInterval = 3000; accessToUnderlyingConnectionAllowed = TRUE; removeAbandoned = ложь; removeAbandonedTimeout = 60; logAbandoned = ложь; connectionProperties = NULL; initSQL = NULL; jdbcInterceptors = NULL; jmxEnabled = TRUE; fairQueue = TRUE; useEquals = TRUE; abandonWhenPercentageFull = 0; MaxAge = 0; useLock = ложь; DataSource = NULL; dataSourceJNDI = NULL; suspectTimeout = 0; alternateUsernameAllowed = ложь; commitOnReturn = ложь; rollbackOnReturn = FALSE; useDisposableConnectionFacade = TRUE; logValidationErrors = FALSE; propagateInterruptState = ложь; ignoreExceptionOnPreLoad = ложь; useStatementFacade = TRUE; }

Настройки часового пояса MySQL:

mysql> SHOW VARIABLES LIKE '%zone%';
+------------------+-----------------------+
| Variable_name    | Value                 |
+------------------+-----------------------+
| system_time_zone | Eastern Standard Time |
| time_zone        | +00:00                |
+------------------+-----------------------+

1 Ответ

0 голосов
/ 24 января 2019

Достаточно было установить часовой пояс JVM в UTC

mvn spring-boot:run -Drun.jvmArguments="-Duser.timezone=UTC"

Это работает для Spring Boot v1. Это другой аргумент для v2. Использование java.time.*, параметров подключения MySQL или установка переменных MySQL не требовалось. Использование LocalDate приведет к ошибке com.fasterxml.jackson.databind.JsonMappingException: Unsupported field: HourOfDay из-за аннотации JSON Jackson с использованием меток времени. Instant работает, хотя.

Я добавил

@SpringBootApplication
public class App extends SpringBootServletInitializer {
    @PostConstruct
    public void init(){
      TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }

Для более близкого паритета DEV / PROD и в случае, если производство случайно получает часовой пояс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...