带时区和毫秒的LocalDateTime格式

5
我将尝试编写一个DateTimeFormatter来解析以下格式:
2020-05-29T07:51:33.106-07:00

我已经查看了ISO_OFFSET_DATE_TIME,但问题在于它不包含毫秒。因此我决定自己写。

没有时区的话很容易实现:

public static void main (String[] args) throws java.lang.Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
    System.out.println(
        LocalDateTime.parse("2020-05-29T07:51:33.106", formatter)
    );
}

它完美地运行

但是当我试图以以下格式添加时区时

public static void main (String[] args) throws java.lang.Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    System.out.println(
        LocalDateTime.parse("2020-05-29T07:51:33.106-07:00", formatter)
    );
}
现在出现异常,提示无法解析时区。
Exception in thread "main" java.time.format.DateTimeParseException: Text '2020-05-29T07:51:33.106-07:00' could not be parsed at index 23
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1951)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at Ideone.main(Main.java:16)

如何解析这种格式的时区?


1
请注意,-07:00 是一个UTC偏移量(ZoneOffset类),而不是时区(ZoneId类)。时区是特定地区人们使用的偏移量过去、现在和未来变化的历史记录。 - Basil Bourque
1
更正:ISO_OFFSET_DATE_TIME 可以很好地解析毫秒。您不需要其他格式化程序。 - Ole V.V.
2个回答

7
从Javadoc中(重点是我的):
偏移Z:基于模式字母的数量格式化偏移。一个、两个或三个字母输出小时和分钟,没有冒号,例如“+0130”。当偏移量为零时,输出将为“+0000”。四个字母输出本地化偏移的完整形式,相当于Offset-O的四个字母。如果偏移为零,则输出相应的本地化偏移文本。五个字母输出小时、分钟,加上非零可选秒,带有冒号。如果偏移为零,则输出“Z”。六个或更多字母会抛出IllegalArgumentException。
将单个“Z”更改为“ZZZZZ”。

6

总结

无需定义格式化程序。

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )

详情

Jim Garrison的答案是正确的。此外,您正在使用错误的类。

LocalDateTime类只表示带有时间的日期,没有其他信息。该类故意缺乏任何时区或偏移量的概念。因此,该类无法表示时刻,不是时间线上的点。

enter image description here

因此,将带有偏移量的字符串(末尾的-07:00)解析为LocalDateTime没有意义。偏移量的有用信息将被忽略且丢弃。

相反,请将其解析为OffsetDateTime

奖励:您的整个格式化程序问题变得无关紧要。您的输入字符串符合默认在OffsetDateTime类中用于解析/生成字符串的标准ISO 8601格式。完全不需要定义任何自定义格式模式。

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )

…并且:

myOffsetDateTime.toString() 

您说:

但是当我尝试添加一个时区时

不,您添加了一个偏移量而不是一个时区,使用的字符串是-07:00

  • 偏移量仅是相对于本初子午线的小时-分钟-秒数。
  • 时区则远不止如此。时区有一个名称,例如America/Edmonton。时区具有过去、现在和未来变化的历史,这些变化与特定地区的人们使用的挂钟时间的偏移量有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接