Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to tell Gson how to parse LocalDateTime and LocalDate, but I'm getting this error, which looks to me like it should match the format. I'm thinking there's either something I don't understand about parsing dates or something I don't understand about 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();
like image 435
Steve Avatar asked Oct 20 '25 22:10

Steve


1 Answers

As @Jon Skeet said in the comments, your pattern has 1 extra digit when compared to the input string, so yyyyMMddHHmmssSSS won't work: the input 2017101800000700 has 16 digits, while the pattern yyyyMMddHHmmssSSS expects 17.


Although the last part (0700) looks like an UTC offset, it's missing a + or - sign (so it should be +0700 or -0700). The offset represents the difference from UTC, and without a sign, it's ambiguous: you can't say if it's ahead or behind UTC.

And even if it's really an offset, I couldn't find a way to parse without a sign: I tried with all the available options and none worked. A sign is always required, so parsing it as an offset is not possible, unless you make an arbitrary assumption (such as "it's positive") and change the input manually, like this:

// 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

This will result in a LocalDateTime equals to:

2017-10-18T00:00


Another alternative is to treat 07 as seconds and the last 2 zeroes as fractions of second.

In this case, a pattern such as yyyyMMddHHmmssSS won't work due to a bug in Java 8 API.

The same link above also provides the workaround: use a java.time.format.DateTimeFormatterBuilder with a java.time.temporal.ChronoField for the fraction of seconds.

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

This will parse the following LocalDateTime:

2017-10-18T00:00:07

Note that it's different from the previous one, because now we're considering 07 to be the seconds.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!