首页 > 解决方案 > 将时间转换为 UTC 时间则相反

问题描述

我正在尝试使用 Java 8 DateTimeFormatter 解析偏移时间。

我生活在 UTC-5 的 EST 时间,所以当我尝试转换时

2019-01-22T13:09:54.620-05:00 应该是 --> 2019-01-22T18:09:54.620

但是,使用我的代码,它获取当前时间并返回 5 小时,导致 2019-01-22 08:09:54.620

代码:


import java.sql.Timestamp
import java.time._
import java.time.format.DateTimeFormatter

import scala.util.{Failure, Success, Try}

class MyTimeFormatter(parser: DateTimeFormatter) {

   def parse(input: String): Try[Timestamp] = {
    Try(new Timestamp(Instant.from(parser.withZone(ZoneOffset.UTC).parse(input)).toEpochMilli))
  }
}

测试:

new MyTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")).parse("2019-01-22T13:09:54.620-05:00") shouldEqual Timestamp.valueOf("2019-01-22T18:09:54.620")

其中解析器是类型DateTimeFormatter,输入字符串只是"2019-01-22T13:09:54.620-05:00"

我想使用这种parser.parse方法,而不是像特定的 temporalAccessorsOffsetDateTime.parse(input, parser)这样我可以处理所有情况,比如LocalTime, LocalDateTime, ZonedDateTime, OffsetDateTime, etc..

似乎代码只是获取时间,减去偏移量,并将其标记为 UTC,而不是计算相对于 UTC 的偏移量。

此外,是否只有当输入格式为 ZonedDateTime/OffsetDateTime 格式时才应用此 UTC 转换?如果我输入 LocalDateTime (没有偏移量),例如2017-01-01 12:45:00解析器仍将应用 UTC 偏移量转换,因为我告诉解析器使用区域 UTC 进行解析。

标签: javascaladatetime-format

解决方案


虽然我无法准确地重现您的问题(即使将时钟更改为 EST),但这是我观察到的:

Instant instant = Instant.from(parser.withZone(ZoneOffset.UTC).parse("2019-01-22T13:09:54.620-05:00"));

这正在产生您期望的时间(2019-01-22T18:09:54.620Z)。

Timestamp ts = new Timestamp(instant.toEpochMilli());

因为这是基于java.util.Date,它显示为您的当地时间。

将 a转换Instant为 a的更好方法Timestamp是通过LocalDateTime,如下所示:

Timestamp ts = Timestamp.valueOf(instant.atZone(ZoneOffset.UTC).toLocalDateTime());

推荐阅读