简体   繁体   中英

Daylight Savings Time shift in Timestamp without timezone

I am using hibernate to communicate with a postgresql database for storing data for modelling. In these models, there are time series that are based on time stamps without timezone. Now, when uploading timestamps that were created correctly (in this case for the year 2030), the timestamp for 2030-03-31T02:00 ends up as 2030-03-31T-03:00 in the database in the column that is a timestamp without timezone. I already changed the Database config so that its timezone is UTC, but the problem stays.

The problem seems to be located either in the driver ( https://mvnrepository.com/artifact/org.postgresql/postgresql/42.2.5 ) or in the database. When inserting the timestamp as string, it works. Also this problem is occuring on a local and a remote DB.

Also, hibernate is in Version 5.4.2 (newest) and in my persistence.xml i set the flag:

<property name="hibernate.jdbc.time_zone" value="UTC"/>

A small test i wrote looks like this:

@Test
   public void testTimeShift() {

       EntityManager em = JPAUtil.createEntityManager();


       TimeStep timeStep = new TimeStep();
       LocalDateTime.now(Clock.systemUTC());
       LocalDateTime ldt = LocalDateTime.parse("2030-03-31T02:00:00");
       timeStep.setTimeStamp(ldt);

       SaveToDB.(timeStep, em);

       em.close();

       EntityManager em2 = JPAUtil.createEntityManager();

       TimeStep timeStep2 = LoadFromDB.getTimeStep(ldt, em2);

       if (timeStep.getTimeStamp() != timeStep2.getTimeStamp()) {
           System.out.println(timeStep.getTimeStamp());
           System.out.println(timeStep2.getTimeStamp());
           throw new EmptyStackException();
       }
   }

This code returns the following:

2030-03-31T02:00
2030-03-31T03:00

Process finished with exit code -1

The Answer is to set the type for the timestamp to ZonedTimeData. This can be parsed from and to LocalDateTime for convenience. That way, the test works.

So, in contrast to what is recommended, for a timestep without timezone use:

@Entity
@Table(name = "`TimeStep`")
public class TimeStep {

   @Column(name = "`TimeStamp`")
   private ZonedDateTime TimeStamp;
}

Creating timesteps ist then done via

LocalDateTime.now(Clock.systemUTC());
LocalDateTime ldt = LocalDateTime.parse("2030-03-31T02:00:00");

ZonedDateTime zonedDateTime = ZonedDateTime.of(ldt, ZoneId.of("UTC"));
timeStep.setTimeStamp(zonedDateTime);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM