ZonedDateTime 格式和格式模式中带有“z”的解析异常

ZonedDateTime format and parsing exception with “z” in format pattern

我在解析时遇到问题 ZonedDateTime:

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-ddzhh:mm");
ZonedDateTime.parse(s, formatter);

这会导致错误:

java.time.format.DateTimeParseException:
    Text '2022-05-24UTC12:15' could not be parsed at index 10

这段代码有什么问题?

字符 z 应该能够解析 "UTC" (在大多数 Locale 中)因为 UTC 被认为是 time-zone IDjava.time 中的 time-zone 名称VV 可以解析 time-zone idsz 可以解析 time-zone-names JavaDocs of java.time.DateTimeFormatter,这里是文档的相关部分:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
(…)

V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name         Pacific Standard Time; PST

(…)

这意味着您可以使用字符 V 解析它,而无需为您的 DateTimeFormatter 提供特定的 Locale。你必须放两个 (VV) 否则你会得到一个漂亮的 IllegalArgumentException 和以下消息:

java.lang.IllegalArgumentException: Pattern letter count must be 2: V

如果您仍想使用 z,请提供一个 Locale,将 UTC 视为 协调世界时 的缩写,Central European Summer Time是一个缩写,在不同的Locale之间肯定会发生变化,例如

  • 英语:CEST
  • 德语:MESZ

其他 Locale 可能有不同的缩写,这让我想知道你的 Locale 是否真的有不同的 UTC
例如提供Locale.ENGLISH,它应该会解析成功。

您无论如何都应该提供一个,因为如果您不这样做,DateTimeFormatter 将隐式使用您的(Java 虚拟)机器的默认 Locale

所以你可以试试这个:

DateTimeFormatter format = DateTimeFormatter.ofPattern("uuuu-MM-ddVVHH:mm");

或者这个:

DateTimeFormatter format = DateTimeFormatter.ofPattern("uuuu-MM-ddzHH:mm", Locale.ENGLISH);

如果您在一天中的几个小时内使用 HH 而不是 hhhh = 12 小时制,HH = 24 小时制)。

是的,这是因为格式化程序模式,我建议使用下面的代码:

    final DateTimeFormatter format
            = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");

    ZonedDateTime zonedDateTime = ZonedDateTime
            .parse("2022-05-24 14:30:30 -01:00", format);
    
    System.out.println(zonedDateTime);

    ZonedDateTime localTimeline = zonedDateTime
            .withZoneSameInstant(ZoneId.systemDefault());

    // for the local timezone
    System.out.println(localTimeline);