为什么在Java 8中OffsetDateTime无法解析'2016-08-24T18:38:05.507 + 0000'

Rya*_*ell 3 java date

表达方式

OffsetDateTime.parse("2016-08-24T18:38:05.507+0000")

导致以下错误:

java.time.format.DateTimeParseException:无法在索引23处解析文本'2016-08-24T18:38:05.507 + 0000'

另一方面,

OffsetDateTime.parse("2016-08-24T18:38:05.507+00:00")

可以正常工作。

DateTimeFormatter的文档页面提到了不带冒号的区域偏移量作为示例。我究竟做错了什么?我不想破坏我的日期字符串来安抚Java。

acm*_*acm 5

您正在调用以下方法。

public static OffsetDateTime parse(CharSequence text) {
    return parse(text, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
Run Code Online (Sandbox Code Playgroud)

DateTimeFormatter.ISO_OFFSET_DATE_TIMEjavadoc中DateTimeFormatter所述,它使用use来执行以下操作:

ISO日期时间格式化程序,用于格式化或解析具有偏移量的日期时间,例如“ 2011-12-03T10:15:30 + 01:00”。

如果您想使用其他格式解析日期,2016-08-24T18:38:05.507+0000则应使用OffsetDateTime#parse(CharSequence, DateTimeFormatter)。以下代码可以解决您的问题:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
OffsetDateTime.parse("2016-08-24T18:38:05.507+0000", formatter);
Run Code Online (Sandbox Code Playgroud)


Arv*_*ash 5

更新

感谢 Ole VV 建议这个更简单的模式:

DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                        .appendPattern("[XXX][XX][X]")
                        .toFormatter(Locale.ENGLISH);
Run Code Online (Sandbox Code Playgroud)

如果单位(例如月、日、小时等)可以是个位数或两位数,原来的答案仍然有用。如果单位为个位数,则此替代模式将失败。

原答案

解决方案是使用DateTimeFormatter带有可选模式的 a 。允许DateTimeFormatter我们在方括号中指定可选模式。

演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
                "u-M-d'T'H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]][XXX][XX][X]",
                Locale.ENGLISH);
        
        // Test
        Stream.of(
                "2021-07-22T20:10:15+0000",
                "2021-07-22T20:10:15+00:00",
                "2021-07-22T20:10:15+00",
                "2021-07-22T20:10:15.123456789+0000",
                "2021-07-22T20:10:15.12345678+0000",
                "2021-07-22T20:10:15.123+0000",
                "2021-07-22T20:10:15.1+0000"                
        ).forEach(s -> System.out.println(OffsetDateTime.parse(s, dtf)));
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

2021-07-22T20:10:15Z
2021-07-22T20:10:15Z
2021-07-22T20:10:15Z
2021-07-22T20:10:15.123456789Z
2021-07-22T20:10:15.123456780Z
2021-07-22T20:10:15.123Z
2021-07-22T20:10:15.100Z
Run Code Online (Sandbox Code Playgroud)

输出Z中的 是零时区偏移的时区指示符。它代表祖鲁语并指定Etc/UTC时区(具有+00:00小时的时区偏移量)。

从Trail: Date Time中了解有关现代日期时间 API 的更多信息。


检查 的文档页面DateTimeFormatter以获取模式字母的完整列表。