【问题标题】:In Java why is LocalDateTime not displaying time according to local timezone?在 Java 中,为什么 LocalDateTime 不根据本地时区显示时间?
【发布时间】:2020-07-01 12:43:40
【问题描述】:

我的代码这样做是为了显示当前日期和时间

DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
String formattedDate = dtf.format(LocalDateTime.now());

因为无论如何我都使用 GMT,所以我没有注意到它总是使用 GMT 时区显示,这是客户在不同时区报告的。但我很困惑,因为我认为 LocalDateTime 是 local 日期时间?

【问题讨论】:

  • 时区显示从何而来?您的日期格式化程序 dtf 是否包含时区?
  • 不,只是更新的问题,时区应该在格式化程序中还是在 dateTime 中?
  • 因为显示时间错误
  • “我以为 LocalDateTime 是本地日期时间” --- 是的!它是 JVM 的 默认时区本地的,就像 documentation 说的,即now() 的 javadoc:从系统获取当前日期时间时钟在默认时区

标签: java datetime


【解决方案1】:

LocalDateTime 没有Zone,而是使用ZonedDateTime

String formattedDate = dtf.format(ZonedDateTime.now());

另外,您的DateTimeFormatter 无法显示该区域,为此,您必须使用FormatStyle.LONG 而不是FormatStyle.MEDIUM

【讨论】:

    【解决方案2】:

    来自javadoc

    日期时间没有时区

    如果你想拥有一个带区域的LocalDateTime,你可以使用atZone()

    ZonedDateTime zdt = someLocalDateTime.atZone(ZoneId.systemDefault());
    String formattedDate = zdt.format(dtf);
    

    【讨论】:

      【解决方案3】:

      客户正在将 UTC 配置为默认时区的系统上运行您的程序。

      您可以告诉客户更改计算机上的时区,或者至少专门针对您的程序,但他们可能不会这样做。运行时钟设置为 UTC 的计算机是有充分理由的。

      另一种解决方案可能是将用户的首选时区添加到您的程序设置中,并始终如一地使用它。例如:

      String userPreferredTz = "Asia/Tokyo"; // Read from user preferences or settings file
      
      ZoneId userZoneId = ZoneId.of(userPreferredTz);
      dtf.format(ZonedDateTime.now(userZoneId))
      

      【讨论】:

      • 是的,这只是用户配置中的一个错误,我无法硬编码时区,因为我有很多客户使用不同的时区。
      • 他们在 NAS 上使用 docker,也许 docker 没有选择系统时区?
      • 我不是建议你硬编码时区。恰恰相反:我建议你让它由用户配置。
      • 这是 docker 的一个常见问题:它默认为 UTC,您必须跳过一些环节才能通过主机时区。 serverfault.com/questions/683605/…forums.docker.com/t/synchronize-timezone-from-host-to-container/…
      • 但是这些链接似乎表明你可以在容器中硬编码不同的时区或将不同的时区作为参数传递给容器,但这超出了我的用户的能力范围,没有办法docker自动使用主机系统的时区?
      【解决方案4】:

      我认为 LocalDateTime 是本地日期时间

      这是正确的。 LocalDateTime 是本地日期时间,即使用系统的默认时区,除非您使用它指定时区,例如如果您在设置为Europe/London 时区的机器上运行以下语句,它将以GMT 显示日期时间,如果您在设置为Asia/Kolkata 时区的机器上运行它,它将以IST 显示日期时间(印度标准时间):

      System.out.println(LocalDateTime.now());
      

      但是,如果您在任何机器上运行以下语句,它将始终为您提供 IST 的日期时间:

      System.out.println(LocalDateTime.now(ZoneId.of("Asia/Kolkata")));
      

      由于LocalDateTimeLocalDate 没有区域或偏移信息,您希望根据您的要求使用ZonedDateTimeOffsetDateTime。下表 (Ref) 为您提供了所有日期时间类的概览,您可以根据需要从中选择一个:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-10
        • 2021-07-12
        • 1970-01-01
        相关资源
        最近更新 更多