我正在做一些测试,以将UTC定义为应用程序的默认时区。首先,我希望将datetime值与UTC一起存储。
根据VLAD MIHALCEA(in another constructor)和https://vladmihalcea.com/how-to-store-date-time-and-timestamps-in-utc-time-zone-with-jdbc-and-hibernate/,我已经在属性文件中进行了设置:
spring.jpa.properties.hibernate.jdbc.time_zone= UTC
为了测试我正在使用h2数据库,我创建了一个具有所有java 8 dateTime类型的示例实体。
在我的liquibase配置中,它们的定义如下:
<column name="instant" type="timestamp"/>
<column name="local_date" type="date"/>
<column name="local_time" type="time"/>
<column name="offset_time" type="time"/>
<column name="local_date_time" type="timestamp"/>
<column name="offset_date_time" type="timestamp"/>
<column name="zoned_date_time" type="timestamp"/>
我认为我在每个字段中都使用好类型。它适用于除“ local_time”,“ offset_time”以外的所有字段,这些字段是Time sql类型而不是timestamp。
https://moelholm.com/2016/11/09/spring-boot-controlling-timezones-with-hibernate/
您可以看到我在上午8:39(巴黎GMT + 2)添加了此行,并且时间戳具有良好的UTC值(上午6:38)。 但是“ local_time”和“ offset_time”的值都奇怪(上午7:39)。
我想知道为什么会有这种行为,如果你们中有些人知道为什么我的两个时间字段不能正确存储值。
PS:版本:
我的示例实体用于插入数据:
import javax.persistence.*;
import java.io.Serializable;
import java.time.*;
import java.util.Objects;
@Entity
@Table(name = "avdev_myData")
public class MyData implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "instant")
private Instant instant;
@Column(name = "local_date")
private LocalDate localDate;
@Column(name = "local_time")
private LocalTime localTime;
@Column(name = "offset_time")
private OffsetTime offsetTime;
@Column(name = "local_date_time")
private LocalDateTime localDateTime;
@Column(name = "offset_date_time")
private OffsetDateTime offsetDateTime;
@Column(name = "zoned_date_time")
private ZonedDateTime zonedDateTime;
答案 0 :(得分:1)
尝试一下:
@SpringBootApplication
public class YourApplication {
@PostConstruct
void started() {
// set JVM timezone as UTC
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
}
答案 1 :(得分:1)
以防在我的情况下决定使用MySQL正常工作
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL57InnoDBDialect
spring.datasource.url = jdbc:mysql:// DBHOST:3306 / DBNAME?useLegacyDatetimeCode = false&serverTimezone = UTC
答案 2 :(得分:1)
我在休眠错误跟踪器中打开了一个问题,并回答了我的问题。
对于LocalTime,转换是相对于1970年1月1日的,而不是我进行测试的日期。因此无法处理DST。
根据Vlad Mihalcea,我们必须改用LocalDateTime,因为我们知道日期,当然知道日期是否在夏令时。
致谢
答案 3 :(得分:0)
spring.datasource.url=jdbc:mysql://...?serverTimezone=Asia/Shanghai
为我工作。
答案 4 :(得分:0)
一旦spring上下文被初始化...。
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationStartUp {
@EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
}
OR
@Component
public class InitializingContextBean implements InitializingBean {
private static final Logger LOG = Logger.getLogger(InitializingContextBean.class);
@Autowired
private Environment environment;
@Override
public void afterPropertiesSet() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
}
答案 5 :(得分:0)
将默认时区设置为UTC不能完全解决我的问题。这就带来了另一个问题,当我记录带有OffsetTime属性的实体时,它以错误的方式吞下了偏移信息和数据保存的数据。例如,18:25 + 03:00变成18:25 + 00:00。我认为这是最糟糕的情况,因为数据已损坏。
为克服此问题且不丢失偏移量信息,我使用了OffsetTime类的withOffsetSameInstant方法并像这样记录了我的实体。
ZoneOffset systemZoneOffset = ZoneId.systemDefault().getRules().getOffset(Instant.now());
OffsetTime offsetTime = clientOffsetTime.withOffsetSameInstant(systemZoneOffset);
最后,这将适用于您计算机所使用的任何时区。这也适用于OffsetDateTime类型的属性。