【问题标题】:How to set timezone of HSQLDB?如何设置 HSQLDB 的时区?
【发布时间】: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


【解决方案1】:

阅读these docs,也许CURRENT_TIMESTAMP 会比NOW 更有效。我目前没有能力对此进行测试,但您可以尝试一下。

既然返回TIMESTAMP WITH TIME ZONE,那么你也可以考虑:

CURRENT_TIMESTAMP AT TIME ZONE INTERVAL '0:00'

See also this discussion thread.

【讨论】:

  • 如果我将NOW 替换为CURRENT_TIMESTAMP,我会得到相同的结果。但是,添加 AT TIME ZONE INTERVAL '0:00' HOUR TO MINUTE 就可以了。谢谢!我现在正在使用以下内容:now() AT TIME ZONE INTERVAL '0:00' HOUR TO MINUTE
猜你喜欢
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 2012-07-04
  • 2011-10-24
  • 2010-10-07
相关资源
最近更新 更多