解析 ZonedDateTime.parse 忽略偏移量
Parsing ZonedDateTime.parse ignoring offset
我正在尝试使用 dd/MM/yy HH:mm:ss zX
格式解析 22/04/17 09:24:28 UTC+01
- 但无论偏移量如何,创建的 ZonedDateTime 都是相同的。
下面是一个重现此示例的示例,我在其中以编程方式更改了偏移量:
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yy HH:mm:ss zX")
.withZone(ZoneId.systemDefault());
System.out.println(MessageFormat.format("Current time is \"{0}\"", formatter.format(Instant.now())));
for (int i = 1; i <= 12; i++) {
final String str = String.format("22/04/17 09:24:28 UTC+%02d", i);
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"", str,
ZonedDateTime.parse(str, formatter)));
}
并且输出:
Current time is "12/07/19 12:59:25 ZZ"
Parsed String "22/04/17 09:24:28 UTC+01", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+02", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+03", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+04", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+05", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+06", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+07", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+08", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+09", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+10", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+11", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+12", got result of "2017-04-22T09:24:28Z[UTC]"
请注意,无论偏移量如何,结果都是相同的。
在您的字符串中,我将 UTC+01
设为与 UTC 相差 +1 小时。因此,虽然 UTC 可能已被解释为时区(实际上不是),但这与此处无关,因为字符串中的时间不是 UTC,而是 UTC+01:00。所以我们不应该使用 z
, time-zone 名称来解析它。这样做基本上是给你错误结果的原因(结合解析成 ZonedDateTime
)。
@VGR 在 his/her 评论中是正确的:我们想要 'UTC'x
。我仅使用两个示例,足以证明它们给出了不同的结果。
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yy HH:mm:ss 'UTC'x");
String str = "22/04/17 09:24:28 UTC+01";
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"",
str, OffsetDateTime.parse(str, formatter)));
str = "22/04/17 09:24:28 UTC+07";
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"",
str, OffsetDateTime.parse(str, formatter)));
输出为:
Parsed String "22/04/17 09:24:28 UTC+01", got result of "2017-04-22T09:24:28+01:00"
Parsed String "22/04/17 09:24:28 UTC+07", got result of "2017-04-22T09:24:28+07:00"
UTC
周围的单引号表示文字文本,因此格式化程序会检查文本是否存在,但认为它没有任何意义。一个 x
是仅由小时组成的偏移量(除非 non-zero 分钟是偏移量的一部分),例如 +01
或 +12
。由于您的字符串包含偏移量且没有时区(例如 Europe/London 表示英国时间),因此 OffsetDateTime
是表示日期和时间的(最)正确类型。
退一步说,虽然您的格式完全适合人类阅读,但 non-standard 并不适合机器解析。您可能要考虑是否可以说服字符串的发送者给您 ISO 8601 格式,例如 2017-04-22T09:24:28+01:00
.
我正在尝试使用 dd/MM/yy HH:mm:ss zX
格式解析 22/04/17 09:24:28 UTC+01
- 但无论偏移量如何,创建的 ZonedDateTime 都是相同的。
下面是一个重现此示例的示例,我在其中以编程方式更改了偏移量:
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yy HH:mm:ss zX")
.withZone(ZoneId.systemDefault());
System.out.println(MessageFormat.format("Current time is \"{0}\"", formatter.format(Instant.now())));
for (int i = 1; i <= 12; i++) {
final String str = String.format("22/04/17 09:24:28 UTC+%02d", i);
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"", str,
ZonedDateTime.parse(str, formatter)));
}
并且输出:
Current time is "12/07/19 12:59:25 ZZ"
Parsed String "22/04/17 09:24:28 UTC+01", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+02", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+03", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+04", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+05", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+06", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+07", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+08", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+09", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+10", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+11", got result of "2017-04-22T09:24:28Z[UTC]"
Parsed String "22/04/17 09:24:28 UTC+12", got result of "2017-04-22T09:24:28Z[UTC]"
请注意,无论偏移量如何,结果都是相同的。
在您的字符串中,我将 UTC+01
设为与 UTC 相差 +1 小时。因此,虽然 UTC 可能已被解释为时区(实际上不是),但这与此处无关,因为字符串中的时间不是 UTC,而是 UTC+01:00。所以我们不应该使用 z
, time-zone 名称来解析它。这样做基本上是给你错误结果的原因(结合解析成 ZonedDateTime
)。
@VGR 在 his/her 评论中是正确的:我们想要 'UTC'x
。我仅使用两个示例,足以证明它们给出了不同的结果。
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yy HH:mm:ss 'UTC'x");
String str = "22/04/17 09:24:28 UTC+01";
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"",
str, OffsetDateTime.parse(str, formatter)));
str = "22/04/17 09:24:28 UTC+07";
System.out.println(MessageFormat.format("Parsed String \"{0}\", got result of \"{1}\"",
str, OffsetDateTime.parse(str, formatter)));
输出为:
Parsed String "22/04/17 09:24:28 UTC+01", got result of "2017-04-22T09:24:28+01:00" Parsed String "22/04/17 09:24:28 UTC+07", got result of "2017-04-22T09:24:28+07:00"
UTC
周围的单引号表示文字文本,因此格式化程序会检查文本是否存在,但认为它没有任何意义。一个 x
是仅由小时组成的偏移量(除非 non-zero 分钟是偏移量的一部分),例如 +01
或 +12
。由于您的字符串包含偏移量且没有时区(例如 Europe/London 表示英国时间),因此 OffsetDateTime
是表示日期和时间的(最)正确类型。
退一步说,虽然您的格式完全适合人类阅读,但 non-standard 并不适合机器解析。您可能要考虑是否可以说服字符串的发送者给您 ISO 8601 格式,例如 2017-04-22T09:24:28+01:00
.