6

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)
André Pacheco
  • 1,780
  • 14
  • 19
  • sry (when it is not obvious to me, but), 1111 AD, BC or something else....? – xerx593 Feb 06 '19 at 20:07
  • This date is just an example, but it was BC (lol) – André Pacheco Feb 06 '19 at 20:09
  • Well, I found some similar questions, but none of them solved this case! =/ – André Pacheco Feb 06 '19 at 20:13
  • 1
    Might be timezone issue? Like if you fetch 2019-02-06T00:00 in +0 zone it is equal to 2019-02-05T23:00 in +1 zone and there you have 2019-02-05 instead of 2019-02-06 while timestamp is acually correct. – ILya Cyclone Feb 06 '19 at 20:16
  • the year (1986) lets me assume: It has something to do with "daylight time saving change" (-> politics) – xerx593 Feb 06 '19 at 20:17
  • @ILyaCyclone that was the first thing I thought. But, how about 1986/1986 years? It just happens for years before 1986. After that everything works perfectly! – André Pacheco Feb 06 '19 at 20:19
  • @ILyaCyclone and as far as I know, LocalDate should not have issues with timezone! It should be independent. – André Pacheco Feb 06 '19 at 20:20
  • 1
    Basically correct, `LocalDate` should not have time zone issues. But sometimes some conversions in retrieval introduce some anyway. What is the datatype of your database column in MySQL? And what time zone are you in? – Ole V.V. Feb 06 '19 at 20:28
  • @OleV.V. the datatype in the database is `date` and I'm in Brazil, currently it's UTC -2 because of DST – André Pacheco Feb 06 '19 at 21:19

2 Answers2

4

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.

André Pacheco
  • 1,780
  • 14
  • 19
  • 1
    Thanks for answering your own question, that’s great. A detail, I believe the recommended way to set a default time zone is through `-Duser.timezone=Etc/UTC` on the Java command line. – Ole V.V. Feb 07 '19 at 20:30
  • 2
    I found that you can also add in `applications.property` these lines: `spring.jackson.date-format=yyyy-MM-dd` and `spring.jackson.time-zone=Brazil/East` In a brief, it's regarding time zone issues. But I don't know why Java is getting this from LocalDate. When I figure this out I want to update this answer. – André Pacheco Feb 07 '19 at 20:40
0

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')
Vy Do
  • 46,709
  • 59
  • 215
  • 313
  • Thank you for your answer, however, it didn't work. I'm still getting the date with one day delayed if the date is before 1985. If it's after 1985 it's working normally! – André Pacheco Feb 06 '19 at 22:51