我知道在成千上万的开发人员每天使用的库中发现错误是冒昧的。所以我认为我的标题问题的答案是“不!!!”,但是......
我有一个对象,其中包含从前端 (JS) 收到的日期,并将其存储到 MongoDB 数据库中。我使用 Spring 来获取这个对象(使用 REST 控制器),并使用 Spring 来执行持久性(使用 MongoDBRepository)。我的计算机配置了 CEST 时钟,因此 GMT+2 (UTC +0200)。
我的 POJO 中的日期存储在 LocalDateTime 中。
这是我的对象:
class Test{
LocalDateTime when;
String data;
// getter setters...
}
以下单元测试显示 Spring(使用 jackson-jsr310)用 UTC 日期时间填充我的 LocalDateTime。
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());
我们可以在杰克逊源代码LocalDateTimeDeserializer.java的第 74 行看到:
return LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC);
但是当我保存在我的数据库中时,spring 使用 spring-data-commons 将我的 LocalDateTime 转换为 Date ,然后再将日期存储在数据库中。我们可以在spring-data-commons/../Jsr310Converters.java中阅读:
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());
}
}
因此,spring-data JSR310 转换器将 localdatetime 解释为默认系统区域中的瞬间。
问题是当我的前端发送“2017-04-03T20:00:00Z”时,REST 控制器将其存储在 LocalDateTime 中,时间如下:20:00:00。而当 mongo-data 转换器将其转换为日期时,得到的时间是 20:00:00+0200(因为我的电脑在 CEST 时区)。
我的结论是我不应该将我的日期存储在 LocalDateTime 中,而应该存储在 Date (java.util) 或 Instant 中。
但是,其中一个转换器是否存在错误?