当前位置: 首页 > 知识库问答 >
问题:

春假本地日期UTC相差一天

沈旻
2023-03-14

我使用Spring Boot 1.5.4、HiberNate 5.2.10、Spring Data REST、HATEOAS、JDK8和LocalDate和LocalDateTime。我的计算机在CEST时区,但我希望应用程序在UTC中工作,所以我设置了application.properties:

spring.datasource.url=jdbc:mysql://localhost:3306/database?useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=true
spring.jpa.hibernate.jdbc.time_zone = UTC

根据这篇文章,我不想更改JVM的时区,因为这似乎不是最佳实践。

Spring Data REST公开了我的存储库,我使用Swagger2有一个很好的接口来使用API。当我尝试一个endpoint时,我看到类似这样的内容:

    {
  "_embedded": {
    "dailyCodes": [
      {
        "sid": "d495cdaa-14f2-44cb-a98f-8aa6ddd43d91",
        "createdDate": "2017-06-28T16:20:01",
        "lastModifiedDate": "2017-06-28T16:20:01",
        "lastModifiedBy": "admin",
        "date": "2017-06-28",
        "code": "js",
        "new": false,
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/v1/dailyCodes/1"
          },
          "dailyCode": {
            "href": "http://localhost:8080/api/v1/dailyCodes/1"
          }
        }
      }

就像你可以看到日期时间格式是好的,它也显示CEST时间,即使在数据库中的实际时间是14:20:01。我想这是错误的,因为我的REST API应该在UTC中工作。

我怎样才能达到这个结果?

总是在同一个主题上,我有一个RESTendpoint(由Spring Data REST公开)要使用LocalDate参数进行搜索;我在用

@Transactional
@PreAuthorize("isAuthenticated()")
public interface DailyCodeRepository extends PagingAndSortingRepository<DailyCode, Long> {

@Query("SELECT d FROM DailyCode d WHERE (:code IS NULL or code=:code) AND (:from IS NULL OR date>=:from) AND (:to IS NULL OR date<=:to)")
    public Page<DailyCode> findAllWithParameter(@Param("code") @RequestParam(value = "code", required = false) String code,
            @Param("from") @RequestParam(value = "from", required = false) LocalDate from,
            @Param("to") @RequestParam(value = "to", required = false) LocalDate to, Pageable pageable);
}

同样在这种情况下,我有一个奇怪的事情:如果我调用传递参数的endpoint,它们在服务器中会少 1 天。到目前为止,接受的日期模式似乎是我的区域设置(意大利语)的JDK默认值,但我想这不是最佳实践。

是否有一个最佳实践可以遵循,以避免在两个方向上的日期/时间参数出现任何问题?

共有1个答案

邵胜涝
2023-03-14

我同意本文作者的观点,即我们必须在UTC中存储和返回时间的API日期和时间的5条法则。“前端”必须自己决定如何根据客户端时区转换时间值。

为了实现这一点(以UTC格式存储和返回时间),我们设置JVM参数-Duser.timezone=UTC或将spring.jpa.properties.hibernate.jdbc.time_zone=UTC添加到application.properties(从Hibernate 5.2.3.Final开始)。然后将实体的时间字段从 LocalDateTime(不存储时区信息)更改为 ZonedDateTime 类型。

之后,时间值将以 UTC 格式存储,独立于启动应用程序的计算机的本地时区,SDR 将以 ISO8601 形式返回这些值:2017-07-02T11:58:10.089Z

但是,如果有必要在特定时区返回时间值,我们必须为所有时间字段设置@JsonForata注释:

@JsonFormat(timezone = "Europe/Rome", pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private ZonedDateTime createdDate;

我们可以在应用程序中定义常量TIME_ZONE,并将其设置为@JsonFormat注释:@JsonFormat(timezone=application.TIME_ZONE,…)

然后我们得到这个输出:

{
    //...
    "createdDate": "2017-07-02T14:11:45.964+0200",
    //...
}

不幸的是,参数<code>spring.jackson。时区(基于我的简短调查)仅影响应用程序中的服务消息,例如:

{
    "timestamp": "2017-07-02T14:14:09.486+0200",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/users"
}

为了以“分区”的形式获取时间,我们必须在application.properties中正确设置spring.jackson.date-format参数:

spring.jackson.date-format=com.fasterxml.jackson.databind.util.StdDateFormat
 类似资料:
  • 问题内容: 我已经为此战斗了一段时间。我正在尝试将纪元转换为日期对象。时代以UTC发送给我。每当您经过一个纪元时,它就会假定它是本地纪元。我尝试创建一个UTC对象,然后使用它来将其调整为适当的纪元,但是似乎有用的唯一方法是字符串对我没有帮助。如果我将该字符串传递给新日期,则应该注意它是UTC,但不是。 我的下一个尝试是尝试获取本地当前时间段与UTC当前时间段之间的差异,但是我也无法做到这一点。 它

  • 问题内容: 从服务器上,我得到了这种格式的datetime变量:它是UTC时间。我想使用JavaScript将其转换为当前用户的浏览器时间。 如何使用JavaScript或jQuery完成此操作? 问题答案: 在将字符串转换为javascript中的日期之前,将’UTC’附加到字符串中:

  • 问题内容: 我从服务器获取UTC时区的字符串日期,我需要将其转换为本地时区。 我的密码: 此打印- utc:2015-04-01T11:42:00.269Z,日期:可选(2015-04-01 11:42:00 +0000) 如果我删除 它打印 utc:2015-04-01T11:42:00.269Z,日期:可选(2015-04-01 08:42:00 +0000) 我的当地时区是UTC +3,在第

  • 问题内容: 我从我的API获取此日期字符串: 但是此日期为UTC格式,我想将其转换为当地时间,该怎么办? 我尝试了这个: 但是它返回了这个错误: 问题答案: 您的日期格式模式错误。改成: 有关更多信息,请参见SimpleDateFormat的javadoc。

  • 我想把这个2021年1月20日20:10:14转换成yyyy-MM-dd'T'HH:MM:ss格式。Android系统中的SSS'Z'。目前我正在使用函数,但当我转换为本地格式时,我没有得到原始时间

  • 在config/app.php中,我将时区设置如下: 这是否意味着在我的应用程序中的任何地方,如果我调用这些carbon方法,它们都将是UTC,或者我仍然需要添加时区,例如carbon::now(“UTC”)?