Как установить часовой пояс на 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 часа от временной метки, сгенерированной кодом, хотя они были сгенерированы с разницей всего в несколько секунд.
Z
в строке ISO8601 это всегда означает UTC. Поэтому, возможно, вы могли бы показать код, где вы выполняете преобразование, и мы могли бы помочь в этом. - person Matt Johnson-Pint   schedule 04.06.2014