如何用Java中的随机秒或纳秒来解析日期时间字符串?

时间:2018-05-17 13:26:33

标签: java parsing datetime serialization

有时你应该反序列化字符串,如" 2018-05-15T09:27:00.65530782Z"这可能看起来像:

  • 2018-05-15T09:27:00.65530Z
  • 2018-05-15T09:27:00
  • 2018-05-15T09:27

然后尝试将DateTimeFormatterBuilder与optionalStart()/ optionalEnd()方法一起使用:

public class CustomDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {

    private DateTimeFormatter fmt = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("yyyy-MM-dd'T'HH:mm")
            .optionalStart()
            .appendLiteral(":")
            .appendFraction(ChronoField.SECOND_OF_MINUTE, 0, 2, false)
            .optionalEnd()
            .optionalStart()
            .appendLiteral(".")
            .optionalEnd()
            .optionalStart()
            .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, false)
            .optionalEnd()
            .optionalStart()
            .appendLiteral("Z")
            .optionalEnd()
            .toFormatter();

    @Override
    public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return ZonedDateTime.of(LocalDateTime.from(fmt.parse(p.getText())), ZoneId.of("UTC"));
    }
}

2 个答案:

答案 0 :(得分:1)

如果您的复杂格式化程序不起作用,另一种方法是填充用零和任何标点符号传递的值,以便始终具有相同的格式。然后,转换那个。

答案 1 :(得分:0)

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .optionalStart()
            .appendPattern("XXX")
            .optionalEnd()
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();

    String[] inputs = {
            "2018-05-15T09:27:00.65530Z",
            "2018-05-15T09:27:00",
            "2018-05-15T09:27",
            "2018-06-12T15:35:01.2344+01:00"
    };

    for (String input : inputs) {
        System.out.println(OffsetDateTime.parse(input, formatter));
    }

输出:

2018-05-15T09:27:00.655300Z
2018-05-15T09:27Z
2018-05-15T09:27Z
2018-06-12T15:35:01.234400+01:00

如果我正确阅读了您的要求,则有两个独立的问题:

  1. 秒数的小数位数可能会有所不同。内置的ISO_LOCAL_DATE_TIME处理它。格式化程序可以嵌套,所以我们只需将它附加到我们自己的fomatter上。
  2. 可以存在或不存在偏移(Z意味着UTC偏移零)。在这里,我使用一个可选部分与parseDefaulting结合使用,以提供在没有偏移时使用的值。
  3. 正如Ivan在a comment中所说,处理不同小数的另一种方法可能是DateTimeFormatterBuilder.appendFraction

    为偏移量(XXX)指定模式而不是坚持匹配文字Z,我们也可以解析其他偏移量,就像上一个输入示例所示。