【问题标题】:How do I indicate to Spring Boot to use UTC time zone for date parameters?如何指示 Spring Boot 使用 UTC 时区作为日期参数?
【发布时间】:2019-03-17 01:22:17
【问题描述】:

我有以下 API

public ResponseEntity<ResponseDataToSeller> getTrackingDataByDate(@RequestBody RequestBodyBySeller requestBodyBySeller) {
    System.out.println(requestBodyBySeller.getEndDate());
    System.out.println(requestBodyBySeller.getEndDate().getDate());
    System.out.println(requestBodyBySeller.getEndDate().getHours());

public class RequestBodyBySeller {
    @ApiModelProperty(dataType="Date", notes = "endDate",required = true)
    Date endDate;

当我使用 "endDate": "2018-10-11" 发出请求时,它会打印出来

2018-10-11 16:54:45.897  INFO 11996 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 3 ms
Wed Oct 10 20:00:00 EDT 2018
10
20

这会弄乱 SQL 查询,因为我正在测试 hit_date &lt;= #{endDate}。它应该返回 2018-10-11 的结果,但事实并非如此,因为 Spring Boot 已将日期解释为 2018-10-10。将日期参数解析到 API 时,如何让 Spring Boot 使用 UTC 时区?

Spring Boot 1.5.13、MyBatis 3.4.5、MyBatis Spring 1.3.1

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    使用local date,问题是当涉及到日期时,java会尝试将日期转换为服务器时区,因为没有指定时区,所以需要UTC时间然后转换,LocalDate不包含时区信息,因此,日期将按原样解析。

    抱歉,忘了提,要处理本地日期时间,您需要使用jackson-datatype-jsr310。然后,如示例所述,您可以使用以下方式注释您的类:

    @JsonFormat(pattern = "dd/MM/yyyy")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate birthdate;*
    

    【讨论】:

    • 那行不通。 Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value ('2018-10-11'); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value ('2018-10-11') at [Source: java.io.PushbackInputStream@56bc399c; line: 1, column: 35]
    • 那不会编译。 Eclipse 给出错误Type mismatch: cannot convert from Class&lt;JodaDeserializers.LocalDateDeserializer&gt; to Class&lt;? extends JsonDeserializer&gt;
    【解决方案2】:

    当你使用springboot时,有一些方法可以在springmvc中定义jackson特性。

    1. 使用属性。 spring.jackson.xxxx。 比如你要设置时区。在您的application.properties 中使用添加spring.jackson.time-zone=xxx

    2. 定义一个实现Jackson2ObjectMapperBuilderCustomizer的spring bean

    3. 你可以直接在spring中创建ObjectMapper bean,自定义你想要的。

    【讨论】:

    • #1 实际上没有用。它仍然打印Wed Oct 10 20:00:00 EDT 2018。即使完全重启。 spring.jackson.time-zone=UTC
    • 你的代码打印''date'显示是EDT时区。所以你可以设置spring.jackson.time-zone=EDT试试。
    • 我想我需要多说一些。您打印“日期”显示 EDT 时区。这个“EDT”来自jvm或你的系统。我认为原因是EDT是UTC 4H之后。所以UTC时间“2018-10-11”更改为EDT时间“Wed Oct 10 20:00:00 EDT 2018"。所以你需要保持时区相同,spring.jackson.time-zone 和 jvm(或系统)时区。
    • 不,我的开发服务器在 EDT 中,时间戳在数据库中,并且是 UTC,并且在 API 中以 UTC 形式给出。我不知道 Spring Boot 如何找到我的时区,因为我没有指定,但它可能会从 JVM 或 Windows 获取它。我不想将时区设置为 EDT。它已经知道我的时区是 EDT。我只想解释 UTC 区域中的日期或使用 UTC 区域设置 Date,因为日期在数据库中作为 UTC 并在 UTC 的 API 中给出。我想让我的开发服务器像生产服务器一样运行在 UTC 区域。
    • 在这种情况下,您应该在 jvm 中使用 UTC 更改时区
    【解决方案3】:

    我把类改成java.time.LocalDate并添加了这个依赖

        <!-- For LocalDate to be deserialized using ISO format -->
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
    

    https://stackoverflow.com/a/46884603/148844

    【讨论】:

      猜你喜欢
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      • 2016-02-17
      • 2021-03-12
      • 1970-01-01
      • 2018-02-24
      • 2019-06-16
      相关资源
      最近更新 更多