【问题标题】:How to generate a java.sql.Timestamp in UTC for a query comparison?如何在 UTC 中生成 java.sql.Timestamp 以进行查询比较?
【发布时间】:2019-11-08 18:41:06
【问题描述】:

我目前正在使用 Spring-Boot 构建一个从 PSQL 数据库读取数据的网关。 PSQL 数据库 v11.3 由运行 Rails 5.1.3 的 Rails Web 应用程序填充。 Spring 应用正在使用 Java 8 和 Spring Data JPA。

相关查询由 Spring 应用程序中的计划方法运行,该方法将当前时间与表的 updated_at 时间进行比较。查询如下:

@Query("SELECT d from SimulatedDeviceEntity d WHERE d.updatedAt > :currentTime")
List<SimulatedDeviceEntity> findByLastUpdated(@Param("currentTime") Timestamp currentTime);

如果我从这个查询中检索一个SimulatedDeviceEntity 并从getUpdatedAt 获取它的时间,它的类型是java.sql.Timestamp。当使用toString() 显示时,我得到2019-06-26 17:24:20.034923 用于在我当地时间13:24 更新的设备。

我尝试了各种关于如何在 UTC 中生成时间戳的答案,包括 here 我创建时间戳的代码是

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("GMT"));
Timestamp currentTime = Timestamp.valueOf(zdt.toLocalDateTime());

无论我尝试什么,在其中任何一个上调用 toString 都会在我的本地时间生成时间戳,比 UTC 晚 4 小时。我已经明白这是故意的,但是当在从 Rails 应用程序检索到的时间戳上调用 toString 时,即使它们以 UTC 显示。 鉴于 toString 应该以当地时间显示时间戳,它以 UTC 时间显示为我的 last_updated 时间的事实让我相信这里还有其他东西在起作用。

【问题讨论】:

标签: java datetime jdbc spring-data-jpa spring-jdbc


【解决方案1】:

实际上,当您比较两个时间戳时,您不需要将它们转换为相同的时区。将它们作为绝对时间进行比较是足够聪明的。它的作用是将任何 Timestamp 转换为自 1.1.1970 00:00 UTC 以来经过的毫秒数的 Long 值,然后将它们进行比较。所以你可能不需要转换你的时间。它应该可以正常工作。

【讨论】:

  • 感谢 Michael 的快速回复,看起来它确实应该可以工作。无论出于何种原因,它似乎仍然将这 4 个小时添加到 updated_at 的时间戳中。这可能是一个转换问题,因为它们最初属于 Ruby 类型 ActiveSupport::TimeWithZone,并且在 Spring 应用程序中检索时它们会被转换为时间戳。也许可能存在翻译问题,即 UTC 与本地时间的偏移实际上被嵌入到时间的 Long 值中?
  • 检查为您的数据库设置的区域设置和时区,看看数据库中写入的时间是否正确。这可能会给你一个提示
  • FWIW,我读到 Java 将所有与日期/时间相关的数据存储为 UTC 中的长值。通常的混淆源于 Java 也是“区域设置感知”并且总是在 LOCAL(每个 JVM)时区中“打印”与日期/时间相关的数据这一事实。解决这个问题的唯一方法是使用,例如,SimpleDateFormat 来配置要在/从哪个时区“打印”。
  • 我将我的 PSQL 数据库的时区更新为 UTC,但这也没有奏效。会继续挖掘。
猜你喜欢
  • 2016-11-12
  • 2017-10-08
  • 2021-05-03
  • 2017-09-07
  • 1970-01-01
  • 2013-11-27
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多