jdbc PostgreSQL 中的偏移时间(带时区的时间)

Posted

技术标签:

【中文标题】jdbc PostgreSQL 中的偏移时间(带时区的时间)【英文标题】:offset time (time with time zone) in jdbc PostgreSQL 【发布时间】:2018-10-15 07:55:39 【问题描述】:

我正在尝试将java.time.OffsetTime 保存并检索到 PostgreSQL 版本 10.5,最新的 JDBC 驱动程序 (v 42.2.5)。

偏移时间已保存,但偏移量无效(它采用应用服务器偏移量而不是传递的偏移量)。

根据:https://jdbc.postgresql.org/documentation/head/8-date-time.html TIME WITH TIMEZONE 不支持(还没有?)。

注意 ZonedDateTime、Instant 和 OffsetTime / TIME [ WITHOUT 不支持 TIMEZONE ]

我的问题是,我想将偏移时间保存到 Postgres 中,那么还有哪些替代方法?

注意,我只关心时间(实际上是一个时间表),但我还需要知道偏移量,以便与 current_time 比较原因。

我的例子:

public class Customer 

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @Column(columnDefinition = "time with time zone")
    private OffsetTime serviceTime;

    @Column(columnDefinition = "timestamp with time zone")
    private OffsetDateTime serviceDateTime;

    private Instant createdDate = Instant.now();

主要:


        OffsetTime serviceTime = OffsetTime.parse("10:00+02:00");
        OffsetDateTime serviceDateTime = OffsetDateTime.now().with(serviceTime);
        System.out.println(serviceTime);
        System.out.println(serviceDateTime);

        Customer customer = new Customer().withName("wael")
                .withServiceTime(serviceTime)
                .withServiceDateTime(serviceDateTime);
        System.out.println("customer: " +  customer);
        customerRepository.save(customer);
    

    
        Customer dbCustomer = customerRepository.findById(1L).get();

        OffsetTime dbServiceTime = dbCustomer.getServiceTime();
        OffsetDateTime dbServiceDateTime = dbCustomer.getServiceDateTime();

        System.out.println(dbServiceTime);
        System.out.println(dbServiceDateTime);
        System.out.println("from db customer: " +  dbCustomer);
    

数据库:

id  created_date    name    service_date_time   service_time
1   2018-10-15 10:38:27.814000  wael    2018-10-15 08:00:00.000000  10:00:00 +03:00

输出:

10:00+02:00
2018-10-15T10:00+02:00
customer: Customer(id=null, name=wael, serviceTime=10:00+02:00, serviceDateTime=2018-10-15T10:00+02:00, createdDate=2018-10-15T07:10:59.900Z)
10:00+03:00
2018-10-15T11:00+03:00
from db customer: Customer(id=1, name=wael, serviceTime=10:00+03:00, serviceDateTime=2018-10-15T11:00+03:00, createdDate=2018-10-15T07:10:59.900Z)

注意,我的机器时区是 +3(因此来自 db 的打印信息是 +3),我的数据库服务器是一个带有 UTC 日期时间设置的 docker 映像。

观察:

OffsetDatetime 已正确保存(作为 UTC)并正确检索。OffsetTime 保存不正确(应该是10:00:00 +02:0011:00:00 +03:00 甚至08:00:00 +00:00 而不是10:00:00 +03:00,检索不正确!)

【问题讨论】:

您是否阅读了有关time with time zone 的comment in the manual? “带时区的类型 time 由 SQL 标准定义,但该定义显示的属性会导致**有问题的有用性” - 可能是一个简单的 time 列和一个 offset 列以分钟为单位存储偏移量是更好的选择。 请注意偏移量与时区不同。 +02:00 是与 UTC 的偏移量。 Europe/Paris 是一个时区(在我输入时恰好位于偏移量 +02:00,但不是全年,也不总是在夏天)。如果您真正需要的是偏移量,那么将您的时间转换为 UTC 是否有效?如果您需要的是时区,我认为最好为时区 ID 定义一个 varchar 列。 @OleV.V.是的,正确,这是因为 DST 规则。我认为 Postgres 使用时区的概念来表达 Offset。 【参考方案1】:

使用 JPA 2.2,您还可以在 Postgresql 中使用 OffsetTime。

@Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE")
private OffsetTime offsetTime;

这就是它在我的数据库中的存储方式:22:00:00.000000 +02:00

【讨论】:

以上是关于jdbc PostgreSQL 中的偏移时间(带时区的时间)的主要内容,如果未能解决你的问题,请参考以下文章

倒带时自动重新加载 TableViewController

使用 JDBC 时,Oracle 的 REF CURSOR 在 Postgresql 中的等价物是啥?

如何通过 Spark 中的 jdbc 连接到 docker 托管的 postgresql 数据库?

Metabase/Clojure 错误:不可冻结类型:类 org.postgresql.jdbc.PgArray

Android上的Postgresql JDBC连接错误

如果插入语句给出重复键异常(在表中找到行 id=1)如何更新 JDBC(Postgresql)中的语句