带有时区和毫秒的 LocalDateTime 格式

Som*_*ame 2 java timezone localdatetime

我正在尝试编写一个DateTimeFormatter来解析以下格式:

2020-05-29T07:51:33.106-07:00
Run Code Online (Sandbox Code Playgroud)

我看过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)
    );
}
Run Code Online (Sandbox Code Playgroud)

它工作得很好

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

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)
    );
}
Run Code Online (Sandbox Code Playgroud)

它现在失败,但无法解析时区。

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)
Run Code Online (Sandbox Code Playgroud)

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

Jim*_*son 8

来自 Javadoc(强调我的):

偏移 Z:这根据模式字母的数量格式化偏移。一个、两个或三个字母输出小时和分钟,不带冒号,例如“+0130”。当偏移量为零时,输出将为“+0000”。四个字母输出完整形式的本地化偏移量,相当于四个字母的 Offset-O。如果偏移量为零,则输出将是相应的本地化偏移文本。五个字母输出小时、分钟,如果非零则可选秒,并带有冒号。如果偏移量为零,则输出“Z”。六个或更多字母将引发 IllegalArgumentException。

将单曲更改ZZZZZZ.


Bas*_*que 5

tl;博士

无需定义格式化程序。

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )
Run Code Online (Sandbox Code Playgroud)

细节

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

LocalDateTime班仅代表用更多的时间的天,没有一个日期。这个类故意缺少任何时区或UTC偏移量的概念。因此,这个类不能代表一个时刻,也不是时间线上的一个点。

在此处输入图片说明

因此,解析带有偏移量的字符串,-07:00最后,作为 aLocalDateTime没有意义。偏移量的有价值信息将被忽略、丢弃。

相反,解析为OffsetDateTime.

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

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )
Run Code Online (Sandbox Code Playgroud)

…和:

myOffsetDateTime.toString() 
Run Code Online (Sandbox Code Playgroud)

你说:

但是当我尝试添加时区时

不,您在字符串中添加了一个从 UTC 开始的偏移量,而不是时区-07:00

  • 偏移量只是本初子午线之前或之后的几个小时-分钟-秒数。
  • 时区要多得多。时区的名称如 America/Edmonton. 时区具有特定地区人民使用的挂钟时间偏移量的过去、现在和未来变化的历史记录。