如何在HSQL数据库中设置时区为UTC ?
根据这里的文档,应该只写:
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()返回localtime, localtime将被插入到数据库中。
因为我们的生产数据库使用UTC时区运行,所以代码被编写为将数据库中的每个时间戳视为UTC。(因此那些withZone(DateTimeZone.UTC)
无处不在)。
在我的单元测试中,我需要比较代码中生成的utc时间戳和数据库中的时间戳。这些单元测试会中断atm,因为数据库中的时间戳(被视为UTC)与代码生成的时间戳相差2小时,尽管它们生成的时间间隔只有几秒钟。
阅读这些文档,也许CURRENT_TIMESTAMP
会比NOW
更好。我目前没有能力测试这个,但你可以试一试。
由于它返回TIMESTAMP WITH TIME ZONE
,那么您还可以考虑:
CURRENT_TIMESTAMP AT TIME ZONE INTERVAL '0:00'