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 ID 和 java.time
中的 time-zone 名称。 VV
可以解析 time-zone ids 而 z
可以解析 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
而不是 hh
(hh
= 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);
我在解析时遇到问题 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 ID 和 java.time
中的 time-zone 名称。 VV
可以解析 time-zone ids 而 z
可以解析 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
而不是 hh
(hh
= 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);