失去了一天的约会
Posted
技术标签:
【中文标题】失去了一天的约会【英文标题】:lost one day for a date 【发布时间】:2015-10-15 19:38:23 【问题描述】:在客户端,我使用 dd/MM/yyyy 日期格式。该字段使用 twitter bootstrap 3 日期时间选择器 (https://eonasdan.github.io/bootstrap-datetimepicker/)
我通过 twitter bootstrap 3 日期时间选择器输入 24/07/2015 在我发送的 json 中,我看到:生日:“24/07/2015”
在我的 dto 中,我愿意
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
private Date birthdate;
当我在服务器上收到日期时,在我的 d 中看到:23/07/2015 19:00
一天过去了。
有什么解释吗?
【问题讨论】:
您是否检查过系统上的当地时间设置? 客户端/服务器在同一台机器上:两者都是 edt -4 小时(mtl 时间)... 绝对是时区转换问题。一方面将时间视为UTC,另一方面将转换为本地时间。我们在与第 3 方系统的某些客户端/服务器集成中遇到了这个问题。死的赠品是加到其他时间的“19:00”,正好是5个小时的时差(实际上不是一整天)。 浏览器端我得到了一个新日期:2015 年 7 月 24 日星期五 23:49:26 GMT-0400 (EDT)。在我得到的服务器上:Fri Jul 23:49:26 EDT 2015. 我认为东部夏令时 (EDT) = GMT-4 (USA + Canada) 如果您使用 Postman 等工具查询您的服务,日期是否不正确?就我而言,问题出在 restTemplate 客户端,而不是在服务器中。 【参考方案1】:我在 java 中遇到了同样的问题。您可以使用 ObjectMapper 设置为默认时区
ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.setTimeZone(TimeZone.getDefault());
这里的解决方案:Jackson @JsonFormat set date with one day less
完整的配置类:
@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters)
for (HttpMessageConverter converter : converters)
if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter)
ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.registerModule(new Hibernate5Module());
mapper.setTimeZone(TimeZone.getDefault());
【讨论】:
【参考方案2】:从日期选择器中选择日期时,我在 JavaScript 中遇到了同样的问题。我使用 .toString() 方法格式化了字段,但该函数给了我一个不同的日期(我也搞砸了一天)。像这样:
var mydate = new Date('2020-04-03');
console.log(mydate.toString());
//Thu Apr 02 2020 20:00:00 GMT-0400 (Eastern Daylight Time)
我改用 .toUTCString() 修复它。
var mydate = new Date('2020-04-03');
console.log(mydate.toUTCString());
//Fri, 03 Apr 2020 00:00:00 GMT
【讨论】:
【参考方案3】:有同样的问题。使用邮递员验证客户端不是罪魁祸首。似乎杰克逊使用的时区与系统的时区存在问题。不得不更改 Jackson 配置以补偿日期
@Configuration
public class JacksonConfig
@Bean
@Primary
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder()
final Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder = new Jackson2ObjectMapperBuilder();
jackson2ObjectMapperBuilder.timeZone(TimeZone.getDefault());
jackson2ObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
jackson2ObjectMapperBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return jackson2ObjectMapperBuilder;
【讨论】:
【参考方案4】:AimZ 的答案是我指出这一点的原因,但我将这三行添加到我的 application.properties 文件中并实现了同样的效果
spring.jackson.date-format=yyyy-MM-dd
spring.jackson.serialization.write-dates-as-timestamps:false
spring.jackson.time-zone:EST
【讨论】:
【参考方案5】:根据JacksonFAQDateHandling页面:
与 TimeZone (java.util.Calendar) 关联的所有时间对象 等)杰克逊构造使用标准时区(GMT),不是 本地时区(无论是什么)。即:杰克逊默认为 使用 GMT 进行所有处理除非另有明确说明。
在您的情况下,日期似乎已自动转换为 GMT/UTC。尝试明确提供您的本地时区以避免 UTC 转换 [如问题中所述这个时间怎么会相差 9 小时? (5 小时、3 小时等) 在同一页]:
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy", timezone="EST")
其次,我认为您正在使用Date.toString()
打印日期。 Note java Date
类与时区无关,但其toString()
方法在打印前使用系统的默认时区。
这里看起来24/07/2015 00:00 UTC
正在被toString()
转换为23/07/2015 19:00 EST
。这两个都代表相同的时刻时间,但在不同的时区。
【讨论】:
我不使用 toString(),但是当@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy") 时,可能会调用 toString。有没有标准的解决方案来管理这个?只保留 gmt 日期...但需要知道某处用户的时区才能正确显示日期。也许某些东西可以与 java 8 或 joda 的新日期一起使用? 最佳实践是将日期/时间信息以 UTC 格式存储在数据库中,并存储用户的时区。然后在向用户显示日期时使用该时区或在存储前删除时区偏移量。有很多文章列出了这种方法的好处,即应用程序可以支持不同的时区。 Java8 Date API 提供了一组新的类来处理日期/时间。这是一篇关于 Java8 Date API dzone.com/articles/deeper-look-java-8-date-and 的好文章。 Java8 或 Joda 简化了日期/时区处理。以上是关于失去了一天的约会的主要内容,如果未能解决你的问题,请参考以下文章