0

I have an entity Person

@Entity
@Data
public class Person {

  @Temporal(TemporalType.DATE)
  private Calendar dob;
}

And some dao classes

@Data
public class PersonResponse {

  @JsonFormat(pattern = "yyyy-MM-dd")
  private Calendar dob;
}
@Data
public class PersonRequest{
  @DateTimeFormat(pattern = "yyyy-MM-dd")
  private Calendar dob;
}

When storing values it works perfectly. Example if I send "2000-01-01" it's stored as is in the database "2000-01-01". But When I try to return it I get "1999-12-31".

Now it's clear that is a Timezone Problem but I don't know how to fix it.

My explanation for the cause

The user timezone is GMT+1 so it is some how retrieved as "2000-01-01T00:00:00.000 +01:00", then parsed to UTC "1999-12-31T23:00:00.000 +00:00" to finally be returned as "1999-12-31".

But why? And how can I prevent this knowing that users timezones can change (so adding the time offset manually of 1 hour won't work).

I tried also changing type from Calendar to java.util.Date and java.sql.Date... but no result.

Similar questions where asked before like this one but I still couldn't understand how to fix it

galalem
  • 389
  • 11
  • 1
    Can you avoid using the cumbersome and long outdated `Calendar` class? `java.util.Date` and `java.sql.Date` are not (much) better. At least if using at least version 5.0 of Hibernate, you can use `LocalDate`. It’s independent of time zone so should eliminate your problem. – Ole V.V. Jun 01 '23 at 10:56
  • Which database engine and which data type in the database? – Ole V.V. Jun 01 '23 at 10:57

2 Answers2

2

If Applicable try to switch from class Calendar to LocalDate. LocalDate does not take time zone into consideration. This should resolve your issue (and simplify your code). Also, for formatting the LocalDate with Json see the answer to this question: Spring Data JPA - ZonedDateTime format for json serialization

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
1

The issue you're facing is indeed related to time zones. When you store the dob value in the database, it's stored as the exact date and time provided. However, when you retrieve it, the time zone conversion takes place, causing the date to appear different. Try use TimeZone.setDefault(TimeZone.getTimeZone("UTC")); and set spring.datasource.url: jdbc:mysql://127.0.0.1:3306/database?serverTimezone=UTC

Ken.Zhang
  • 56
  • 2
  • While setting the default time zone of the program may be a good idea: (1) Don’t use the outdated `TimeZone` class for that. Start the program with JVM argument `-Duser.timezone=UTC`. (2) It’s fragile because someone else may exactly use `TimeZone` to override the value you set. This can be done not only from any part of the program but also from any other program running in the same JVM. – Ole V.V. Jun 04 '23 at 03:36