title: Spring Boot repository returns wrong value when persisting LocalDate with Liquibase configuration
body: <p>I have a small Spring Boot project; all the application does is persist a simple entity with a LocalDate and a LocalDateTime. To ensure uniform date formatting across application servers in different time zones, I set the default Java timezone to UTC after startup.</p>
  
  <p>I have a set of integration tests (using an in-memory H2 database) that save an entity to the database, retrieve it, and check to make sure no properties were mutated. When these tests rely on Hibernate to create the schema using @Entity introspection, the tests pass. However, when I include Liquibase on the classpath and point to a valid configuration file, the tests fail on an equality assertion on the date values, with the persisted LocalDate value consistently coming back as the day before the value of the unsaved entity.</p>
  
  <p>Based on my observations so far, I'm guessing that Liquibase does some kind of initialization and sets a time offset based on the Java environment before my <code>@PostConstruct</code> method has a chance to change the default timezone. If so, how do I properly configure Liquibase to pick up the correct timezone after initialization? Why is LocalDate affected by LocalDateTime not? Why is it consistently giving me the previous day's date instead of behaving more predictably based on my initial time zone settings?</p>
  
  <p>The relevant classes, configurations and results are below. Thanks to anyone who can help me unravel this!</p>
  
  <p>DatePersistenceApplication.java:</p>
  
  <pre><code>@SpringBootApplication
  public class DatePersistenceApplication {
  
      public static void main(String[] args) {
          SpringApplication.run(DatePersistenceApplication.class, args);
      }
  
      public DatePersistenceApplication() {
          TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
      }
  }
  </code></pre>
  
  <p>DatePersistenceEntity.java:</p>
  
  <pre><code>@Entity
  public class DatePersistenceEntity {
  
      @Id private UUID id = UUID.randomUUID();
      @Column private LocalDate localDate;
      @Column private LocalDateTime localDateTime;
  
      public UUID getId() {
          return id;
      }
  
      public LocalDate getLocalDate() {
          return localDate;
      }
  
      public void setLocalDate(LocalDate localDate) {
          this.localDate = localDate;
      }
  
      public LocalDateTime getLocalDateTime() {
          return localDateTime;
      }
  
      public void setLocalDateTime(LocalDateTime localDateTime) {
          this.localDateTime = localDateTime;
      }
  }
  </code></pre>
  
  <p>DatePersistenceRepository.java:</p>
  
  <pre><code>public interface DatePersistenceRepository extends PagingAndSortingRepository&lt;DatePersistenceEntity, UUID&gt; { }
  </code></pre>
  
  <p>DatePersistenceApplicationTests.java:</p>
  
  <pre><code>@RunWith(SpringRunner.class)
  @SpringBootTest
  public class DatePersistenceApplicationTests {
  
      @Autowired private DatePersistenceRepository repository;
  
      @Test
      public void dateTimePreservedDuringSave() {
          DatePersistenceEntity entity = getTestEntity();
          repository.save(entity);
          DatePersistenceEntity savedEntity = repository.findById(entity.getId()).orElseThrow(() -&gt; new RuntimeException("Expected a valid entity"));
          assertEquals("LocalDateTime was transformed during persistence", entity.getLocalDateTime(), savedEntity.getLocalDateTime());
      }
  
      @Test
      public void datePreservedDuringSave() {
          DatePersistenceEntity entity = getTestEntity();
          repository.save(entity);
          DatePersistenceEntity savedEntity = repository.findById(entity.getId()).orElseThrow(() -&gt; new RuntimeException("Expected a valid entity"));
          assertEquals("LocalDate was transformed during persistence", entity.getLocalDate(), savedEntity.getLocalDate());
      }
  
      private DatePersistenceEntity getTestEntity() {
          DatePersistenceEntity entity = new DatePersistenceEntity();
          entity.setLocalDate(LocalDate.now());
          entity.setLocalDateTime(LocalDateTime.now());
          return entity;
      }
  }
  </code></pre>
  
  <p>application.properties:</p>
  
  <pre><code>spring.liquibase.change-log = classpath:db/liquibase-changelog.xml
  </code></pre>
  
  <p>liquibase-changelog.xml:</p>
  
  <pre><code>&lt;?xml version="1.1" encoding="UTF-8" standalone="no"?&gt;
  &lt;databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"&gt;
  
      &lt;changeSet author="example" id="create-date-persistence-entity"&gt;
          &lt;createTable tableName="date_persistence_entity"&gt;
              &lt;column name="id" type="UUID"&gt;
                  &lt;constraints nullable="false"/&gt;
              &lt;/column&gt;
              &lt;column name="local_date_time" type="TIMESTAMP"&gt;
                  &lt;constraints nullable="false"/&gt;
              &lt;/column&gt;
              &lt;column name="local_date" type="TIMESTAMP"&gt;
                  &lt;constraints nullable="false"/&gt;
              &lt;/column&gt;
          &lt;/createTable&gt;
          &lt;addPrimaryKey columnNames="id" constraintName="date_entity_pk" tableName="date_persistence_entity"/&gt;
      &lt;/changeSet&gt;
  
  &lt;/databaseChangeLog&gt;
  </code></pre>
  
  <p>Results of <code>mvn test</code>:</p>
  
  <pre><code>[INFO] Results:
  [INFO]
  [ERROR] Failures:
  [ERROR]   DatePersistenceApplicationTests.datePreservedDuringSave:33 LocalDate was transformed during persistence expected:&lt;2018-02-06&gt; but was:&lt;2018-02-05&gt;
  [INFO]
  [ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0
  </code></pre>
  
  <p>Notes:</p>
  
  <ul>
  <li>My tests are being run in the PST timezone. Based on some limited experimenting, time of day does not seem to affect the test results.</li>
  <li>If I remove the <code>Timezone.setDefaullt(...)</code> call in the <code>@PostConstruct</code> method, or pass <code>-Duser.timezone=UTC</code> in as a JVM argument, both tests pass</li>
  <li>If I run the tests using HSQL instead of H2 as the backing database, both tests pass</li>
  <li>If I disable the Liquibase integration by removing the dependency from the classpath, both tests pass</li>
  <li>Adding the <code>spring.jpa.properties.spring.hibernate.jdbc.time_zone = UTC</code> property in application.properties has no effect.</li>
  </ul>