DateTimeFormatterBuilder在Java 8中使用,特别是选项

whi*_*fin 8 java datetime jodatime java-8

我正试图从Joda迁移到Java 8 ZonedDateTime,我正在用一个DateTimeFormatterBuilder似乎无法解决的问题.

我想接受以下任何格式:

2013-09-20T07:00:33
2013-09-20T07:00:33.123
2013-09-20T07:00:33.123+0000
2013-09-20T07:00:33.123Z
2013-09-20T07:00:33.123Z+0000
2013-09-20T07:00:33+0000
Run Code Online (Sandbox Code Playgroud)

这是我目前的建设者:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .optionalStart()
        .appendPattern(".SSS")
        .optionalEnd()
        .optionalStart()
        .appendZoneId()
        .optionalEnd()
        .optionalStart()
        .appendPattern("Z")
        .optionalEnd()
        .toFormatter();
Run Code Online (Sandbox Code Playgroud)

我可能错了,但似乎应该匹配我想要的模式......对吗?

如果有人能指出我可能错过的东西,我们将不胜感激.我也不太确定如何使用appendOffset,如果事实证明是答案的话,那么对它的清晰度也是值得赞赏的.

编辑:

Text '2013-09-20T07:00:33.061+0000' could not be parsed at index 23
Run Code Online (Sandbox Code Playgroud)

查看构建器,由于可选阶段,这似乎匹配?

编辑2:

在看到第一个答案的建议后,我尝试了这个:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .optionalStart()
        .appendPattern(".SSS")
        .optionalEnd()
        .optionalStart()
        .appendZoneOrOffsetId()
        .optionalEnd()
        .toFormatter()
Run Code Online (Sandbox Code Playgroud)

它继续在上面的字符串上失败.

编辑3:

最新测试导致此异常:

java.time.format.DateTimeParseException: Text '2013-09-20T07:00:33.061+0000' could not be parsed at index 23
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:582)
Run Code Online (Sandbox Code Playgroud)

sai*_*oms 12

这可能是因为它+0000不是区域ID,而是区域偏移.

文档提供了这份名单:

  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
       O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
       X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
       x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
       Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
Run Code Online (Sandbox Code Playgroud)

您可以使用appendOffset("+HHMM", "0000")(doc)或appendZoneOrOffsetId()(doc)代替appendZoneId().

所以你的完整格式化程序可能如下所示

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .optionalStart()
                .appendPattern(".SSS")
                .optionalEnd()
                .optionalStart()
                .appendZoneOrOffsetId()
                .optionalEnd()
                .optionalStart()
                .appendOffset("+HHMM", "0000")
                .optionalEnd()
                .toFormatter();
Run Code Online (Sandbox Code Playgroud)

此外,创建ZonedDateTime的方式可能会影响是否存在异常.因此,我推荐以下内容,因为这没有任何例外.

LocalDateTime time = LocalDateTime.parse("2013-09-20T07:00:33.123+0000", formatter);
ZonedDateTime zonedTime = time.atZone(ZoneId.systemDefault());
Run Code Online (Sandbox Code Playgroud)

  • 基本上我会说没有,但我不确定`2013-09-20T07:00:33.123Z + 0000`因为它有cero-time Z和+0000偏移量.据我所知,这次Z和+0000的意思相同. (2认同)