Как установить часовой пояс HSQLDB?

Как установить часовой пояс на UTC в базе данных HSQL?

Согласно документации здесь нужно просто написать:

SET TIME ZONE INTERVAL '+00:00' HOUR TO MINUTE;

но это не работает для меня.

Я использую HSQLDB (v2.2.8) в качестве базы данных памяти в сочетании с hibernate (v4.2.2) для модульного тестирования и JodaTime (v2.3) для данных, связанных со временем. Некоторые данные вставляются SQL-скриптами через hibernate.hbm2ddl.import_files. Эти скрипты используют функцию now() для создания метки времени.

Однако, когда я извлекаю вставленное значение из базы данных и конвертирую его в UTC, я получаю следующие результаты:

Без какой-либо SQL-команды, подобной приведенной выше:
2014-06-04T16:44:45.193Z
Это мое текущее местное время, но в формате UTC.

С помощью приведенной выше SQL-команды: (обратите внимание на разницу в 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(), '[email protected]', '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 +
            '}';
}
}

Обратите внимание, что в моей конкретной проблеме важны только геттеры, потому что данные НЕ вставляются вручную (например, создание объекта и сохранение в спящем режиме), а с помощью вышеупомянутого SQL-скрипта.

Общая проблема:
База данных не хранит информацию о часовом поясе с фактическим значением метки времени. Поэтому, если now() возвращает локальное время, локальное время будет вставлено в базу данных.

Поскольку наша производственная база данных работает с часовым поясом UTC, код написан так, чтобы каждая временная метка из базы данных воспринималась как UTC. (Поэтому эти withZone(DateTimeZone.UTC) везде).
В своих юнит-тестах мне нужно сравнивать временные метки UTC, сгенерированные в коде, с временными метками из базы данных. Эти модульные тесты ломают банкомат, потому что временная метка из базы данных, обработанная как UTC, отличается на 2 часа от временной метки, сгенерированной кодом, хотя они были сгенерированы с разницей всего в несколько секунд.


person Thomas Eizinger    schedule 04.06.2014    source источник
comment
Для начала рассмотрите возможность сохранения значения в формате UTC. Преобразования могут быть сделаны на входе и выходе. Также обратите внимание, что при отображении Z в строке ISO8601 это всегда означает UTC. Поэтому, возможно, вы могли бы показать код, где вы выполняете преобразование, и мы могли бы помочь в этом.   -  person Matt Johnson-Pint    schedule 04.06.2014
comment
Я знаю, что Z в конце означает UTC. Это нормально, потому что я преобразовал значение в UTC после чтения из базы данных. Я на самом деле ХОЧУ сохранить значение как UTC, но вызов now() в сценарии вставки вставляет его в мое локальное время, и поскольку информация о часовом поясе не хранится с фактическим значением, я получаю неверный результат, если я обрабатываю значение в база данных как UTC. Я добавлю код для пояснения.   -  person Thomas Eizinger    schedule 04.06.2014


Ответы (1)


Прочитав эти документы, возможно, CURRENT_TIMESTAMP будет работать лучше, чем NOW. В настоящее время у меня нет возможности проверить это, но вы можете попробовать.

Поскольку он возвращает TIMESTAMP WITH TIME ZONE, вы также можете рассмотреть:

CURRENT_TIMESTAMP AT TIME ZONE INTERVAL '0:00'

См. также эту ветку обсуждения.

person Matt Johnson-Pint    schedule 04.06.2014
comment
Я получаю те же результаты, если заменяю NOW на CURRENT_TIMESTAMP. Однако добавление AT TIME ZONE INTERVAL '0:00' HOUR TO MINUTE помогло. Спасибо! Сейчас я использую следующее: now() AT TIME ZONE INTERVAL '0:00' HOUR TO MINUTE - person Thomas Eizinger; 04.06.2014