Java/Kotlin 中时区的操作逻辑是什么?

What is logic of manipulation with timezones in Java/Kotlin?

假设我的数据库中保存了客户的时间 2020-09-22T10:50:37.276240900

我需要根据客户端时区在客户端应用程序的 Web 服务中显示此日期,例如,如果客户端居住在 UTC+2 时区,我需要将保存的日期增加 2 小时。

那我在做什么?

从实体获取日期并将时区添加到从数据库获取的时间 (startDate: LocalDateTime)

entity.startDate.atZone(ZoneId.of("Europe/Vienna"))

是什么赋予了我 ZonedDateTime 2020-09-22T10:50:37.276240900+02:00[Europe/Vienna]

的价值

这个值正是我所期望的,基本上是“初始时间加 2 小时”。之后,我将这次格式化为添加了这 2 小时的输出,某种形式的

12:50 22.09.2020

但是当我像这样格式化时

entity.startDate
 .atZone(ZoneId.of("Europe/Vienna"))
 .format(DateTimeFormatter.ofPattern(NotificationListener.EUROPEAN_DATE_FORMAT, Locale.ENGLISH))

其中 const val EUROPEAN_DATE_FORMAT = "HH:mm dd.MM.yyyy"

我得到这个输出 10:50 22.09.2020 ,看起来我的格式应用不正确,所以我看不到我的 2 小时。

所以我的问题是:

  1. 我按照描述的方式添加客户端应用的时区是否正确?
  2. 如何以更精确的方式应用时区并格式化此日期以查看应用的时区?

LocalDateTime.atZone 不会“移动”时间点。事实上,它试图呈现给定时区中的 local 时间正是 LocalDateTime 显示的时间点。

换句话说:如果您的 LocalDateTime 在某个日期表示 10:00,那么 atZoneZonedDateTime 输出也将表示 10:00 指定时区的本地时间(由于 DST 更改而导致本地时间不存在的情况除外)。

因此,如果您存储的时间实际上是 UTC 时间,则需要再添加一个步骤:

ZonedDateTime utcTime = entity.startDate.atZone(ZoneOffset.UTC);
ZonedDateTime localTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Vienna"));

或者,您可以避免每次都计算本地时间,而是将 DateTimeFormatter 配置为使用给定时区(这意味着它将在内部进行必要的计算)using DateTimeFormatter.withZone。如果这样做,则可以直接将 utcTime 传递给它。