Estoy haciendo algunas pruebas para definir UTC como zona horaria predeterminada para mi aplicación. En primer lugar, quiero que mis valores de fecha y hora se almacenen con el UTC.

De acuerdo a VLAD MIHALCEA (https://vladmihalcea.com/how-to-store-date-time-and-timestamps-in-utc-time-zone-with-jdbc-and-hibernate/) y https://moelholm.com/2016/11 / 09 / spring-boot-control-timezones-with-hibernate / he configurado en mi archivo de propiedades:

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

Para probar estoy usando la base de datos h2, he creado una entidad de muestra con todo el tipo de fecha y hora de Java 8.

En mi configuración liquibase se definen así:

<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"/>

Creo que estoy usando el tipo bueno para todos los campos. Funciona para todos los campos, excepto para "local_time" "offset_time", que son tipos de sql de tiempo y no de fecha y hora.

enter image description here

Como puede ver, agregué esta fila a las 8:39 a.m. (GMT de París + 2) y las marcas de tiempo tienen el buen valor UTC (6:38 a.m.). PERO tanto "local_time" como "offset_time" tienen un valor extraño (7:39 am).

Me pregunto por qué este comportamiento, si alguno de ustedes tiene una idea de por qué mis dos campos de tiempo no almacenan valores correctamente.

PS: versión:

  • Hibernate: 5.2.17.Final
  • Bota de primavera: 2.0.4.

Mi muestra de entidad utilizada para insertar datos:

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;
3
Avdev4j 17 sep. 2018 a las 11:38

5 respuestas

La mejor respuesta

Abrí un problema en el rastreador de errores de hibernación y obtuve una respuesta a mi problema.

Para LocalTime, la transformación es relativa al 1 de enero de 1970, no el día en que ejecuté la prueba. Entonces el DST no se maneja.

Según Vlad Mihalcea, tenemos que usar LocalDateTime en su lugar porque sabemos la fecha y, por supuesto, si está en período de horario de verano o no.

Aquí está la respuesta completa: https://hibernate.atlassian.net/browse/HHH-12988?focusedCommentId=103750&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-103750

Saludos

1
Avdev4j 2 oct. 2018 a las 06:15

Una vez que se inicializa el contexto de primavera ...

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"));

    }   

}

O

@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"));
    }
}
0
Tiago Medici 31 may. 2019 a las 12:57

En caso de que decida usar MySQL en mi caso funciona correctamente con

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL57InnoDBDialect

spring.datasource.url = jdbc: mysql: // DBHOST: 3306 / DBNAME? useLegacyDatetimeCode = false & serverTimezone = UTC

1
Petko Mirchev 21 sep. 2018 a las 20:18

Pruebalo:

@SpringBootApplication
public class YourApplication {

    @PostConstruct
    void started() {
        // set JVM timezone as UTC
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}
5
Bendy Zhang 17 sep. 2018 a las 08:53
spring.datasource.url=jdbc:mysql://...?serverTimezone=Asia/Shanghai

Funciona para mi.

  1. Hibernate DEBE reflejar la zona horaria mysql.
  2. mysql jdbc debería reflejar la zona horaria mysql.
1
softwarevamp 31 may. 2019 a las 12:10