【发布时间】:2014-07-25 07:20:35
【问题描述】:
如何在 HSQL 数据库中将时区设置为 UTC?
根据文档here 应该只写:
SET TIME ZONE INTERVAL '+00:00' HOUR TO MINUTE;
但这对我不起作用。
我使用 HSQLDB (v2.2.8) 作为内存数据库,结合 hibernate (v4.2.2) 进行单元测试和 JodaTime (v2.3) 用于时间相关数据。
通过hibernate.hbm2ddl.import_files 使用SQL 脚本插入一些数据。这些脚本使用now() 函数来创建时间戳。
但是,当我从数据库中检索插入的值并将其转换为 UTC 时,我得到以下结果:
没有像上面那样的任何 SQL 命令:2014-06-04T16:44:45.193Z
这是我当前的当地时间,但在 UTC。
使用上面的 SQL-Command:(注意 1 小时的差异)2014-06-04T15:50:56.688Z
如果我们这里没有夏令时,这将是本地时间。
可能有趣的一点:我在上述命令中提供的偏移量无关紧要,输出总是相同的。
编辑:
我的插入脚本的示例行:
INSERT INTO public.users
(created_at, modified_at, email, firstname, lastname, password, state, image_id)
VALUES
(now(), now(), 'max.mustermann@example.com', 'Max', 'Mustermann', 'password_hash', 'ACTIVE', NULL);
我的用户实体继承自以下实体:
@MappedSuperclass
public abstract class AbstractTrackedEntity extends AbstractEntity {
@Column(name = "created_at")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
DateTime createdAt;
@Column(name = "modified_at")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
DateTime modifiedAt;
public DateTime getCreatedAt() {
return createdAt.withZone(DateTimeZone.UTC);
}
public void setCreatedAt(DateTime createdAt) {
this.createdAt = createdAt.withZone(DateTimeZone.UTC);
}
public DateTime getModifiedAt() {
return modifiedAt.withZone(DateTimeZone.UTC);
}
public void setModifiedAt(DateTime modifiedAt) {
this.modifiedAt = modifiedAt.withZone(DateTimeZone.UTC);
}
@PrePersist
protected void onCreate() {
modifiedAt = createdAt = DateTime.now(DateTimeZone.UTC);
}
@PreUpdate
protected void onUpdate() {
modifiedAt = DateTime.now(DateTimeZone.UTC);
}
@Override
public String toString() {
return "AbstractTrackedEntity{" +
"createdAt=" + createdAt +
", modifiedAt=" + modifiedAt +
'}';
}
}
请注意,在我的特定问题中,只有 getter 是相关的,因为数据不是手动插入的(例如,创建实体并使用 hibernate 持久化)而是使用上述 SQL 脚本。
问题总结:
数据库不存储带有实际时间戳值的时区信息。因此,如果 now() 返回本地时间,本地时间将被插入到数据库中。
由于我们的生产数据库使用时区 UTC 运行,因此编写代码以将数据库中的每个时间戳都视为 UTC。 (因此到处都是withZone(DateTimeZone.UTC))。
在我的单元测试中,我需要将代码中生成的 UTC 时间戳与数据库中的时间戳进行比较。这些单元测试会破坏 atm,因为数据库中的时间戳(被视为 UTC)与代码生成的时间戳相差 2 小时,尽管它们的生成时间仅相隔几秒钟。
【问题讨论】:
-
考虑以 UTC 存储值开始。可以在进出时进行转换。另请注意,在 ISO8601 字符串中显示
Z时,始终表示 UTC。因此,也许您可以在您进行转换的地方显示代码,我们可以在那里提供帮助。 -
我知道尾随的 Z 表示 UTC。这很好,因为我在从数据库读取后将值转换为 UTC。我实际上想将值存储为 UTC,但是在插入脚本中调用 now(),将其插入到我的本地时间,并且因为没有时区信息与实际值一起存储,如果我将值处理在数据库为 UTC。我将添加一些代码以进行澄清。
标签: java hibernate timezone jodatime hsqldb