在 JPA MySQL 中存储与时区无关的时间的最佳方式



我在 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;
...

start_time和end_time映射为本地时间,因为本地时间不存储时区信息。但是,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 中使用它们进行查询很乏味。 有更好的解决方案吗?

更新

我必须使用服务器的时区获取当前班次。因此,如果我在数据库中将时间存储为 UTC,然后我查询它们将当前服务器时间转换为 UTC 不起作用,因为在夏令时 (DST( 期间,服务器时区增加了 1。因此,在冬季,07:00:00+01 转换为 06:00:00 UTC。但是,在夏季,07:00:00+02 将转换为 05:00:00 UTC。

欢迎来到 SO

最好将带有UTC时区的日期存储在数据库中,并在客户端进行转换。您可以设置以下属性以强制 JPA 使用 UTC

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

希望这个 hleps

你可以看看这个博客

最新更新