Date issue in spring boot data rest

2019-06-24 14:42发布

问题:

I'm having a problem with spring data rest when I'm handling dates. In a brief, it is delaying the date in one day. For example, if I have 1111-11-11 it returns to me 1111-11-10.

There are some related post here in SO (ex1, ex2, ex3), but none of them solved the problem.

I have an entity with this LocalDate:

@Column(nullable=true)
private LocalDate birthDate;

I also have this repository:

@RepositoryRestResource(collectionResourceRel = "person", path = "person")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long>{

}

When I save the birthDate in the database (I'm using MySQL), it saves correctly. However, when I make this query, for example:

Person p = personRepo.findById(1L).get();

The date is fetched with one day late (just like in the example above). I tried to implement this suggestion, that is, change the LocalDate to Date and include the Jackson annotation, but it doesn't work. I also tried to include the jackson-modules-java8, but the problem still.

Now the most intriguing thing. As I was just testing I was including the date 1111-11-11. I changed that for today's date 2019-02-06. Then, the fetch works! At this time, I think if it was a problem with very old dates. Thus, I tried, for example, 1970-01-01, and the spring returned 1969-12-31. I realized that if I include in the database dates above 1986-01-01 everything works fine. However, if I include anything below that, I got the date one day late.

Is someone has some hint about this issue?

Thank you for your time!

EDIT: I also checked my database timezone and it's ok!

+--------------------+---------------------+--------------------+
| @@GLOBAL.time_zone | @@session.time_zone | @@system_time_zone |
+--------------------+---------------------+--------------------+
| SYSTEM             | SYSTEM              | -02                |
+--------------------+---------------------+--------------------+
1 row in set (0,00 sec)

回答1:

Finally, I found a solution. After the @ILyaCyclone and @OleV.V. comments, I started to search about timezone, spring boot, and LocalDate. Indeed the LocalDate doesn't carry UTC information. However, when I fetch this data from the database, the JVM needs to make a conversion to make the SQL date become the LocalDate.

Therefore, the first thing I made was to check the database timezone:

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) as GMT_TIME_DIFF;

which returned:

+--------------------+---------------------+--------------------+
| @@GLOBAL.time_zone | @@session.time_zone | @@system_time_zone |
+--------------------+---------------------+--------------------+
| SYSTEM             | SYSTEM              | -02                |
+--------------------+---------------------+--------------------+

and:

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)

returning:

+--------------------------------+
| TIMEDIFF(NOW(), UTC_TIMESTAMP) |
+--------------------------------+
| -02:00:00                      |
+--------------------------------+

All these SQL answers were ok. So, the problem was in the spring boot. What solved the problem was to set the UTC in the code. I found this hint here.

@PostConstruct
void started() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}

After that, all the dates started to work properly.

Is solved the problem. However, I have no clue about the issue regarding the date after and before 1986. If someone has some hint, please share with me.

Thank you guys who put some effort to help me. I really appreciate that.



回答2:

Use dependency https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-hibernate5

For example, if you use Gradle

implementation ('com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.9.8')