【问题标题】:java.time.format.DateTimeParseException could not be parsed at index 0java.time.format.DateTimeParseException 无法在索引 0 处解析
【发布时间】:2018-04-04 13:45:02
【问题描述】:

我试图告诉 Gson 如何解析 LocalDateTimeLocalDate,但我收到了这个错误,在我看来它应该与格式匹配。我在想要么是我不了解解析日期,要么是我不了解 Gson。

java.time.format.DateTimeParseException:无法在索引 0 处解析文本“2017101800000700”

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();

【问题讨论】:

  • 好吧 2017101800000700 不适合 yyyyMMddHHmmssSSS - 你没有足够的数字。 (日期后面是00000700,HHmmss为000007,SSS只剩下00。)
  • 但我怀疑 0700 实际上是从 UTC 偏移的时区。
  • @JonSkeet 唯一奇怪的事情(如果 0700 是偏移量)是缺少 +- 符号,所以它是一个模棱两可的偏移量。还是没有标志就意味着积极?
  • @Hugo:同意,这很奇怪。

标签: java gson java-time datetime-parsing localdate


【解决方案1】:

作为@Jon Skeet said in the comments,与输入字符串相比,您的模式多出 1 位数字,因此 yyyyMMddHHmmssSSS 将不起作用:输入 2017101800000700 有 16 位数字,而模式 yyyyMMddHHmmssSSS 需要 17 位。


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

即使它真的是一个偏移量,我也找不到没有符号的解析方法:我尝试了all the available options,但没有一个成功。符号始终是必需的,因此无法将其解析为偏移量,除非您做出任意假设(例如 “它是正数”)并手动更改输入,像这样:

// 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 视为秒,将最后两个零视为秒的小数部分。

在这种情况下,yyyyMMddHHmmssSS 这样的模式将由于bug in Java 8 API 而不起作用。

上面的相同链接也提供了解决方法:在几分之一秒内使用 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 视为秒。

【讨论】:

    猜你喜欢
    • 2018-12-12
    • 1970-01-01
    • 2020-06-25
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    相关资源
    最近更新 更多