java.time.format.DateTimeParseException 无法在索引 0 处进行解析

java.time.format.DateTimeParseException could not be parsed at index 0

我试图告诉 Gson 如何解析 LocalDateTimeLocalDate,但我收到了这个错误,在我看来它应该与格式匹配。我在想关于解析日期或者我不理解 Gson 的东西。

java.time.format.DateTimeParseException: Text '2017101800000700' could not be parsed at index 0

Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
    @Override
    public LocalDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
    }
  }).registerTypeAdapter(LocalDate.class, new JsonDeserializer<LocalDate>() {
    @Override
    public LocalDate deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return LocalDate.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyyMMdd"));
    }
  }).create();

由于 ,与输入字符串相比,您的模式多了 1 个数字,因此 yyyyMMddHHmmssSSS 不起作用:输入 2017101800000700 有 16 个数字,而模式yyyyMMddHHmmssSSS 预计 17。


尽管最后一部分 (0700) 看起来像 UTC offset,但缺少 +- 符号(因此应该是 +0700-0700)。偏移量表示与UTC的差异,没有符号,它是模棱两可的:你不能说它是领先还是落后于UTC。

即使它真的是一个偏移量,我也找不到没有符号的解析方法:我尝试使用 all the available options 并且 none 有效。始终需要符号,因此无法将其解析为偏移量,除非您做出任意假设(例如"it's positive")并更改输入手动,像这样:

// assuming the offset "0700" is positive (7 hours ahead UTC)
String dateStr = "2017101800000700";

// insert the "+" manually, so input becomes 201710180000+0700
dateStr = dateStr.substring(0, 12) + "+" + dateStr.substring(12, 16);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMddHHmmXX");
System.out.println(LocalDateTime.parse(dateStr, fmt)); // 2017-10-18T00:00

这将导致 LocalDateTime 等于:

2017-10-18T00:00


另一种方法是将 07 视为秒,将最后 2 个零视为秒的小数部分。

在这种情况下,由于 bug in Java 8 API.

yyyyMMddHHmmssSS 等模式将不起作用

上面相同的 link 也提供了解决方法:使用 java.time.format.DateTimeFormatterBuilderjava.time.temporal.ChronoField 作为秒数。

String dateStr = "2017101800000700";
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // date/time
    .appendPattern("yyyyMMddHHmmss")
    // milliseconds (with 2 digits)
    .appendValue(ChronoField.MILLI_OF_SECOND, 2)
    // create formatter
    .toFormatter();
System.out.println(LocalDateTime.parse(dateStr, fmt)); // 2017-10-18T00:00:07

这将解析以下 LocalDateTime:

2017-10-18T00:00:07

请注意,它与上一个不同,因为现在我们考虑 07 为秒。