Лучший способ хранить независимое от часового пояса время в JPA MySql - PullRequest
4 голосов
/ 15 февраля 2020

Я не могу найти хорошее решение в JPA для хранения времени, не зависящего от часового пояса, в mysql дБ.

У меня есть таблица смен, где мне нужно хранить время начала и окончания для каждая смена.

+-------------+--------------+------+-----+----------+----------------+
| Field       | Type         | Null | Key | Default  | Extra          |
+-------------+--------------+------+-----+----------+----------------+
| id          | int(11)      | NO   | PRI | NULL     | auto_increment |
| name        | varchar(64)  | NO   |     | NULL     |                |
| start_time  | time         | NO   |     | 00:00:00 |                |
| end_time    | time         | NO   |     | 00:00:00 |                |
+-------------+--------------+------+-----+----------+----------------+

Таким образом, время начала / окончания, извлеченное из mysql, должно рассматриваться как строки (без применения определенного часового пояса). Но если я сохраню их как varchar (8), я не смогу использовать следующий запрос (без применения какого-либо преобразования типов из varchar во время).

select * from shift where ('21:30:00' BETWEEN start_time and end_time );

Итак, я хочу сохранить возможность сравнивать их как раз.

Я попытался смоделировать таблицу сдвига следующим образом:

    @Entity
    public class Shift {
      @Id
      private Long id;

      @Column(name = "name")
      private String name;

      @Column(name = "start_time")
      private LocalTime startTime;

      @Column(name = "end_time")
      private LocalTime endTime;

...

Время начала и end_time отображаются как LocalTime, потому что LocalTime не хранит информацию о часовом поясе. Но Hibernate преобразует java .util.Date каждой записи, извлеченной из LocalTime, применяя системный часовой пояс по умолчанию, следующим образом:

    if ( Date.class.isInstance( value ) ) {
        final Date ts = (Date) value;
        final Instant instant = Instant.ofEpochMilli( ts.getTime() );
        return LocalDateTime.ofInstant( instant, ZoneId.systemDefault() ).toLocalTime();
    }

Таким образом, результирующее время начала / окончания относится к часовому поясу сервера.

Решение состоит в том, чтобы хранить их как целые числа и делить часы на минуты. Таким образом, таблица сдвига будет иметь четыре столбца: start_hours, start_minutes, end_hours, end_minutes. Но делать запросы, используя их в JPA, утомительно. Есть лучшее решение?

ОБНОВЛЕНИЕ

Я должен получить текущую смену, используя часовой пояс сервера. Поэтому, если я храню время в формате UT C в БД, а затем запрашиваю их, преобразование текущего времени сервера в UT C не работает, потому что в летнее время (DST) часовой пояс сервера увеличивается на единицу. Итак, зимой 07: 00: 00 + 01 конвертируется в 06:00:00 UT C. Но летом 07: 00: 00 + 02 преобразуется в 05:00:00 UT C.

1 Ответ

1 голос
/ 15 февраля 2020

Добро пожаловать в SO

Всегда лучше хранить даты с UT C TimeZone в базе данных и выполнять преобразование на стороне клиента. Вы можете установить свойство ниже, чтобы заставить JPA использовать UT C

spring.jpa.properties.hibernate.jdbc.time_zone=UTC

Надеюсь, что это поможет

Вы можете взглянуть на этот блог

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...