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 小时。
所以我的问题是:
- 我按照描述的方式添加客户端应用的时区是否正确?
- 如何以更精确的方式应用时区并格式化此日期以查看应用的时区?
LocalDateTime.atZone
不会“移动”时间点。事实上,它试图呈现给定时区中的 local 时间正是 LocalDateTime
显示的时间点。
换句话说:如果您的 LocalDateTime
在某个日期表示 10:00,那么 atZone
的 ZonedDateTime
输出也将表示 10:00 指定时区的本地时间(由于 DST 更改而导致本地时间不存在的情况除外)。
因此,如果您存储的时间实际上是 UTC 时间,则需要再添加一个步骤:
ZonedDateTime utcTime = entity.startDate.atZone(ZoneOffset.UTC);
ZonedDateTime localTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Vienna"));
或者,您可以避免每次都计算本地时间,而是将 DateTimeFormatter
配置为使用给定时区(这意味着它将在内部进行必要的计算)using DateTimeFormatter.withZone
。如果这样做,则可以直接将 utcTime
传递给它。
假设我的数据库中保存了客户的时间 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 小时。
所以我的问题是:
- 我按照描述的方式添加客户端应用的时区是否正确?
- 如何以更精确的方式应用时区并格式化此日期以查看应用的时区?
LocalDateTime.atZone
不会“移动”时间点。事实上,它试图呈现给定时区中的 local 时间正是 LocalDateTime
显示的时间点。
换句话说:如果您的 LocalDateTime
在某个日期表示 10:00,那么 atZone
的 ZonedDateTime
输出也将表示 10:00 指定时区的本地时间(由于 DST 更改而导致本地时间不存在的情况除外)。
因此,如果您存储的时间实际上是 UTC 时间,则需要再添加一个步骤:
ZonedDateTime utcTime = entity.startDate.atZone(ZoneOffset.UTC);
ZonedDateTime localTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Vienna"));
或者,您可以避免每次都计算本地时间,而是将 DateTimeFormatter
配置为使用给定时区(这意味着它将在内部进行必要的计算)using DateTimeFormatter.withZone
。如果这样做,则可以直接将 utcTime
传递给它。