I am trying to parse the following date string received from a Bitbucket event payload:

2017-09-19T10:39:36+1000

When the incoming date is in offset +0000 then it works but +1000 does not.

This is a slightly non-standard (from the JDK's perspective) date string in that it has no colon in the offset. So I have made a custom DateTimeFormatter that works when the offset is +0000:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .optionalStart()
    .appendOffset("+HHMM", "+0000")
    .optionalEnd()
    .toFormatter();

However, when the offset is +1000 as above, it fails with:

Cannot deserialize value of type java.time.OffsetDateTime from String "2017-09-19T10:39:36+1000": Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException) Text '2017-09-19T10:39:36+1000' could not be parsed at index 19

If the received date string is using offset +0000 then it works. How can I parse all time zones?

Update - Extra context:

This is being used to construct an instance of JavaTimeModule used to inform the ObjectMapper of the incoming date format:

JavaTimeModule javaTimeModule = new JavaTimeModule();
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .optionalStart()
    .appendOffset("+HHMM", "+0000")
    .optionalEnd()
    .toFormatter();
// This also fails:
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssx");
LocalDateTimeDeserializer deserializer = new LocalDateTimeDeserializer(formatter);
javaTimeModule.addDeserializer(LocalDateTime.class, deserializer);
// MAPPER is an instance of com.fasterxml.jackson.databind.ObjectMapper
MAPPER.registerModule(javaTimeModule);

2 Answers

0
Ninad Ingole On

For parsing +1000 this below code will work.

package com.iamninad.qa;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TimeFormat {

    public static void main(String[] args) throws IOException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
        System.out.println(dateTimeFormatter.parse("2017-09-19T10:39:36+1000"));
        LocalDateTimeDeserializer deserializer = new LocalDateTimeDeserializer(dateTimeFormatter);

        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addDeserializer(LocalDateTime.class, deserializer);
        ObjectMapper MAPPER = new ObjectMapper();
        MAPPER.registerModule(javaTimeModule);

        // serialize object

        String s = MAPPER.writeValueAsString(new Data());
        System.out.println(s);

        // deserialize object

        String json = "{\"date\":\"2017-09-19T10:39:36-0830\"}";
        String json1 = "{\"date\":\"2017-09-19T10:39:36+1000\"}";

        Data data = MAPPER.readValue(json, Data.class);
        System.out.println(data.toString());

        Data data1 = MAPPER.readValue(json1, Data.class);
        System.out.println(data1.toString());
    }

}

class Data {
    // Just to generate a sample data
    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
    private LocalDateTime date = LocalDateTime.parse("2017-09-19T10:39:36+1000", dateTimeFormatter);

    public LocalDateTime getDate() {
        return date;
    }

    public void setDate(LocalDateTime date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "Data{" +
                "date=" + date +
                '}';
    }
}

If you want to parse +10:00 then use ISO_OFFSET_DATE_TIME for fields in format +10:00 or pattern yyyy-MM-dd'T'HH:mm:ssXXX it will either be in any one format. I guess this issue is resolved in jdk 9

OffsetDateTime.parse("2017-09-19T10:39:36+10:00")

Also parses time in only one format i.e +10:00 and not in +1000 you need to specify formatter to parse method

OffsetDateTime.parse("2017-09-19T10:39:36+1000",DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZZZ"))
0
assylias On

The Z pattern can parse that offset. Have you tried to use this:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .append(ISO_LOCAL_DATE_TIME)
        .appendPattern("Z")
        .toFormatter();

It can parse +0000 and +1000.