首页 > 解决方案 > 如何让我的 Spring Boot API 返回 MySQL 日期值的 UTC 时间而不是“2018-08-01T04:00:00Z”?

问题描述

如何让 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)中,并尝试通过添加 4 小时将其转换为 UTC。它在一切都设置为 UTC 的生产环境中工作。我的本地系统时区设置为东部标准时间。我试过了

初始化时我的数据源:

数据源 = org.apache.tomcat.jdbc.pool.DataSource@67c7bbdf{ConnectionPool[defaultAutoCommit=null; 默认只读=空;默认交易隔离=-1;默认目录=空;driverClassName=com.mysql.jdbc.Driver; 最大活动=100;最大空闲=100;分钟空闲=10;初始大小=10;最大等待=30000;testOnBorrow=真;测试返回=假;timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=假;测试连接=假;密码=********;url=jdbc:mysql://localhost:3306/appdb?useSSL=false&useUnicode=yes&characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=UTC; 用户名=根;validationQuery=/* ping */ SELECT 1; 验证查询超时=-1;验证器类名=空;验证间隔=3000;accessToUnderlyingConnectionAllowed=true; 删除放弃=假;removeAbandonedTimeout=60; 日志放弃=假;连接属性=空;初始化SQL=空;jdbc拦截器=空;jmxEnabled=真;公平队列=真;使用等于=真;放弃当百分比满=0;最大年龄=0;使用锁=假;数据源=空;数据源JNDI=空;怀疑超时=0;备用用户名允许=假;提交返回=假;回滚返回=假;useDisposableConnectionFacade=true; 日志验证错误=假;传播中断状态=假;忽略异常OnPreLoad=假;useStatementFacade=true; } 传播中断状态=假;忽略异常OnPreLoad=假;useStatementFacade=true; } 传播中断状态=假;忽略异常OnPreLoad=假;useStatementFacade=true; }

我的 MySQL 时区设置:

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

标签: javamysqlspringspring-bootjackson

解决方案


将 JVM 时区设置为 UTC 就足够了

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

这适用于 Spring Boot v1。对于 v2,这是一个不同的论点。不需要使用java.time.*、MySQL 连接参数或设置 MySQL 变量。由于 JSON Jackson 注释使用时间戳,使用LocalDate会出错。不过确实有效。com.fasterxml.jackson.databind.JsonMappingException: Unsupported field: HourOfDayInstant

我添加了

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

为了更接近 DEV/PROD 平价,以防生产意外设置时区。


推荐阅读