jooqUTC本地日期时间在保存和加载之间变化



我的同事使用jooq创建了一个postgresql数据库。从那时起,我们创建了带有字段和LocalDateTime.now(ZoneOffset.UTC(值的对象。当这些字段被保存到该数据库并在几个小时后再次读取时,我们的数据对象发生了变化:

public class PlannedInvoice
{
private UUID accountId;
private LocalDateTime billingTime;
}

保存方法如下所示:

LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
UUID accountId = UUID.randomUUID();
PlannedinvoiceRecord record = plannedInvoiceService.create();
record.setAccountid(accountId.toString());
record.setBillingtime(now.atOffset(ZoneOffset.UTC));
record.store();

读取方法如下:

return dsl.selectFrom(PLANNEDINVOICE)
.where(PLANNEDINVOICE.ACCOUNTID.eq(accountId.toString()))
.fetchOneInto(PlannedInvoice.class);

数据库目前使用timestamp with time zone,但我也很乐意将其替换为实际的LocalDateTime,以完全避免这些问题(JOOQ支持这一点(!

当我们保存一个值LocalDateTime.of(2020, Month.AUGUST, 13, 0, 0)时,它将在数据库中为2020-08-12 20:00:00-04。这似乎仍然是正确的。

从数据库中读取值似乎是出错的地方。在读取方法之后,billingTime的值为2020-08-12 20:00:00。在我看来,在重建数据对象时,fetchOneInto似乎忽略了时区。

那么,为什么在保存UTC值时会有转换,为什么从数据库中读取这些值时没有转换呢?这对我来说似乎很违反直觉。我宁愿避免任何时区转换。

对我有用的是用OffsetDateTime创建一个临时读取对象,然后使用withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime()进行转换。最终修复它相当容易。数据库和/或jooq会将数据转换到其他时区,这从一开始就违反直觉。

这是新的对象:

public class PlannedInvoiceWithOffset
{
private UUID accountId;
private OffsetDateTime billingTime;
}

一个新的构造函数,用于创建所需的数据对象并将时区调整为UTC:

public PlannedInvoice(PlannedInvoiceWithOffset tempObject)
{
this.accountId = tempObject.getAccountId();
this.billingTime = tempObject.getBillingTime().withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();
}

现在我的读取方法是这样的:

public PlannedInvoice findByAccountId(UUID accountId)
{
PlannedInvoiceWithOffset temp = dsl.selectFrom(PLANNEDINVOICE)
.where(PLANNEDINVOICE.ACCOUNTID.eq(accountId.toString()))
.fetchOneInto(PlannedInvoiceWithOffset.class);
return new PlannedInvoice(temp);
}

最新更新