java - 如何让我的 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 的生产环境中工作。我的本地系统时区设置为东部标准时间。我试过了
&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"
初始化时我的数据源:
数据源 = 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 |
+------------------+-----------------------+
解决方案
将 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: HourOfDay
Instant
我添加了
@SpringBootApplication
public class App extends SpringBootServletInitializer {
@PostConstruct
public void init(){
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
为了更接近 DEV/PROD 平价,以防生产意外设置时区。
推荐阅读
- c - 将exe反编译映射回C语言
- r - 乘以 R 增加的百分比
- python - pd.read_html 读取一个空表
- amazon-ec2 - Amazon aws route53,将子域重定向到在特定端口下运行的 ec2 应用程序
- c# - 如何检查子模型状态是否有效,而不是检查 asp.net 核心中的主模型状态?
- android - Android片段ClassNotFoundException:找不到类android.support.constraint.ConstraintLayout
- tcl - 如何在 TCL 脚本中将字符串从说英语翻译成日语
- c# - 方法“ImageAnnotatorClient.Create”没有重载需要 1 个参数
- android - Android Java 与 Native C 未定义的对 `__android_log_print' 的引用
- javascript - TypeError:Webpack 导入的模块不是函数