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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With