Spring Boot 应用程序中的 Jackson 时区属性。yaml 在 IDE 中有效,但在 docker 容器中无效

问题描述 投票:0回答:1

好的,首先要全面披露。我正在开发一个在其实体和 dto 对象上使用 java.util.Date 的项目,我们正在努力更改为 LocalDateTime。当 Jackson 在控制器层将我们的 dto 对象序列化为 JSON 时,我们自然会遇到时区问题。我们正在努力将日期更改为 LocalDateTime,但在此期间,设置以下属性:

  jackson:
    time-zone: Canada/Pacific

用于将日期/时间转换为正确的值。但是,我们的应用程序部署为托管在 Openshift 上的 docker 容器。一旦进入 docker,即使在我的本地机器上,我也可以将此值更改为任何值,并且日期永远不会改变。我已经尝试检查 linux 容器中的 TZ 值,它与我们的时区等匹配。有什么想法吗?

java spring-boot docker jackson openshift
1个回答
0
投票

tl;博士

使用

java.time.Instant
,而不是
java.time.LocalDateTime
。时区没问题。

使用
Instant
,而不是
LocalDateTime

在其实体和 dto 对象上使用 java.util.Date,我们正在努力更改为 LocalDateTime

LocalDateTime
是这里使用的错误类。该类故意缺少任何时区或与 UTC 的偏移量的概念。因此,该类的对象不能代表时间轴上的一个时刻、一个特定点。只需一个日期和一天中的某个时间,我们就有办法知道您指的是东京、图卢兹还是托莱多的那个时间——例如,相隔几个小时的三个截然不同的时刻。

替换

java.util.Date
的类是
java.time.Instant
。两者都代表一个时刻,时间轴上的一个特定点,如与 UTC 的零时分秒偏移量所示。

👉所以使用

Instant
。您的时区问题完全消失了。

ISO 8601

当文本序列化为 JSON、XML 等时,仅使用标准 ISO 8601 格式。在 UTC 中,这会像这样:

2023-04-28T19:31:41.078125Z
。末尾的
Z
+00:00
的缩写,偏移量为零;发音为“祖鲁”。

java.time 类在解析/生成文本时默认使用 ISO 8601 格式。无需指定格式模式。

String output = myInstant.toString() ;

……和:

Instant myInstant = Instant.parse( input ) ;

应用时区

要通过特定时区的挂钟时间查看那一刻,请应用

ZoneId
以获得
ZonedDateTime

ZoneId z = ZoneId.of( "America/Vancouver" ) ;
ZonedDateTime zdt = myInstant.atZone( z ) ;  // Same moment as the `Instant` object, but different wall-clock time & possibly different date.

在此代码中,

myInstant
zdt
都代表同一时刻,即时间轴上的同一时间点。就像在不列颠哥伦比亚省温哥华和雷克雅未克冰岛互相打电话的两个人一样,如果两个人同时抬头看各自墙上的日历和时钟,他们会看到一天中的不同时间,甚至可能是不同的日期。

避免默认区域

当 Jackson 序列化我们的 dto 时,我们自然会遇到时区问题

你是unnecessarily introducing time zone where it is not needed.

注意上面的代码是如何不依赖于默认时区的。编写代码以避免隐式依赖于 JVM 当前的默认时区。始终传递可选的时区参数。

© www.soinside.com 2019 - 2024. All rights reserved.