问题
I know that's presumptuous to image found a bug in a library used every day by thousands of developpers. So I think the answer to my title question is "NO !!!", but ...
I have an object containing a date that I receive from my front end (JS), and I store it into a MongoDB database. I use Spring to get this object (with a REST Controller), and Spring to perform persistance (with a MongoDBRepository). My computer is configured with a CEST clock, so GMT+2 (UTC +0200).
The date in my POJO is stored in a LocalDateTime.
Here is my object :
class Test{
LocalDateTime when;
String data;
// getter setters...
}
The following unit test show that Spring (which use jackson-jsr310) fill my LocalDateTime with an UTC Date Time.
mockMvc.perform(post("/test")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"when\":\"2017-03-31T14:20:28.000Z\",\"data\":\"toto\"}")).andExpect(status().isOk());
List<com.robopec.models.Test> tests = testRepository.findAll();
Assert.assertEquals(14, tests.get(0).getWhen().getHour());
We can see in the jackson source code LocalDateTimeDeserializer.java line 74 :
return LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC);
But when I save in my database, spring use spring-data-commons to convert my LocalDateTime to a Date before storing the date in the database. We can read in spring-data-commons/../Jsr310Converters.java this :
public static enum LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> {
INSTANCE;
@Override
public Date convert(LocalDateTime source) {
return source == null ? null : Date.from(source.atZone(systemDefault()).toInstant());
}
}
So, spring-data JSR310 Converters interpret a localdatetime as an instant in the default system zone.
The problem is that when my front end send "2017-04-03T20:00:00Z", the REST controller store it in a LocalDateTime with the following time : 20:00:00. And when the mongo-data converter convert it into a date, the resulting time is 20:00:00+0200 (because my computer is in CEST time zone).
My conclusion is that I shouldn't store my date in a LocalDateTime but rather in a Date (java.util) or in an Instant.
But, is there a bug in one of the converters ?
回答1:
If I remember correctly, the latest version of the Java driver for mongoDB still use java.util.Date to store dates, so using the Java 8 time api can be a bit of a hassle.
In one project I work on, I switched from Joda Datetime to the Java 8 time a few months ago. I couldn't get my way around with LocalDateTime, ZonedDateTime and so on, so I decided to go with Instant and it worked fine. Just remember to use the ISO8601 Zulu notation for your dates ("2017-03-31T14:20:28.000Z"), which is already what you're doing apparently.
来源:https://stackoverflow.com/questions/43194043/is-it-a-bug-in-jackson-datatype-jsr310-deserializer