TLDR:
Как всегда сохранять правильное значение даты и времени UTC в поле типа DATETIME баз данных H2 и MySQL с помощью Java Hibernate?
Полный контекст:
У меня есть таблица с полем DATETIME в базе данных, и я хочу вставить строки, где:
- по умолчанию (когда значение не указано) будетсохраняется текущее время UTC
- или, если указано время даты UTC, оно должно храниться без дополнительных преобразований часового пояса.
Проблема в том, что он должен работать в локальной базе данных H2, кака также на локальном mysql внутри Docker и на внешнем экземпляре AWS RDS MySQL.
И мне трудно найти дату и время для правильного сохранения во всех 3 экземплярах.
Пока это либоэкземпляры local и aws mysql получают правильные значения, но локальный H2 получает неправильное значение, или наоборот, когда локальный H2 получает правильное значение, но экземпляры MySQL получают неправильные значения.
Вот сокращенный фрагментs кода Котлина, который у меня есть.
Код, который работает для H2, но не работает для MySQL в Docker и AWS:
@Entity
data class SomeEntity(
val createdAt: LocalDateTime = LocalDateTime.now(Clock.systemUTC())
// If createdAt is not explicitly given when saving new entry in db, the default value will be used
// and H2 will get correct value of '2019-03-28 12:36:56',
// but it will be wrong for MySQL, it will get '2019-03-28 11:36:56'
)
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss")
createdAt = LocalDateTime.parse("2012-11-30 16:13:21", dateTimeFormatter)
// In this case when createdAt is explicitly given when saving new entry in db,
// H2 gets correct value '2012-11-30 16:13:21',
// but MySQL DBs will get wrong value of '2012-11-30 17:13:21'
Кодэто работает для MySQL в Docker и AWS, но не работает для H2:
@Entity
data class SomeEntity(
val createdAt: Date = Date()
// If createdAt is not explicitly given when saving new entry in db, the default value will be used
// and MySQL DBs will get correct value of '2019-03-28 12:36:56'
// but it will be wrong for H2 as it will get '2019-03-28 13:36:56' (my current local time instead of UTC)
)
val dateTimeFormatter = SimpleDateFormat("yyyy-MM-dd H:mm:ss")
dateTimeFormatter.timeZone = TimeZone.getTimeZone("UTC")
createdAt = dateTimeFormatter.parse("2012-11-30 16:13:21")
// In this case when createdAt is explicitly given when saving new entry in db,
// MySQL DBs will get correct value '2012-11-30 16:13:21',
// but H2 will get wrong value of '2012-11-30 17:13:21'
Это работает на: Spring Boot 2.1.3 , Hibernate Core 5.3.7 , MySQL 8.0.13 , H2 1.4.197
Я видел кучу вопросов в Интернете, а также о stackoverflow, но, к сожалению, ни один изрешения могут решить мою проблему.
Обновление
После дополнительной отладки с несколькими подходами, просматривая журналы Hibernate, H2 и MySQL, похоже, что время UTC обрабатываетсямежду H2 и MySQL - совершенно противоположный путь.
Сохранение в локальную H2:
- [неверно] с использованием
Date
, когда UTC составляет 09:55 , значение журнала Hibernate «Пт мар 29 10: 55 : 09 CET 2019», оно сохраняется как «2019-03-29 10: 55 : 09.412". - [неправильно], используя
Instant
,когда UTC составляет 16: 48 , значение журнала Hibernate «2019-03-28T 16: 48 : 18.270Z» сохраняется как «2019-03-28 17:48 : 18,27 ". - [неправильно] с использованием
OffsetDateTime
, когда UTC составляет 10: 11 , значение журнала Hibernate" 2019-03-29T 10: 11: 30,672Z ", он сохраняется как" 2019-03-29 11: 11 : 30,672 ". - [правильно] с использованием
LocalDateTime
, когда UTC составляет 16: 50 , значение журнала Hibernate "2019-03-28T 16: 50 : 20,697", оно сохраняется как "2019-03-28 16: 50 : 20,697".
Сохранение в MySQL в локальном докере:
- [правильно] с использованием
Date
, когда UTC 09: 51 , значение журнала Hibernate "Пт мар 29 10: 51 : 56 CET 2019", оно сохраняется как "2019-03-29 09: 51 : 56,519". - [исправить], используя
Instant
, когда UTC равно 09: 38 , значение журнала Hibernate "2019-03-29T 09: 38 : 59.172Z", оно сохраняется как«2019-03-29 09: 38 : 59,172». - [правильно] с использованием
OffsetDateTime
, когда UTC составляет 10: 14 , значение журнала Hibernate "2019-03-29T 10: 14 : 22,658Z", сохраняется как "2019-03-29 10: 14 : 22,658". - [неправильно] с использованием
LocalDateTime
, когда UTC составляет 16: 57 , значение журнала Hibernate "2019-03-28T 16: 57 : 35,631", оно сохраняется как"2019-03-28 15: 57 : 35,631".