piotrek
piotrek

Reputation: 14550

Jackson: parse ZonedDateTime with timezone id

With Spring MVC (Spring boot) I can deserialize ZonedDateTime from

2016-07-26T05:30:47+01:00

but not from

2016-07-26T05:30:47+01:00 Europe/Paris

How can I explicitly add timezone and still be able to deserialize it?

Upvotes: 3

Views: 6921

Answers (1)

user7605325
user7605325

Reputation:

You can specify a pattern with an optional section (delimited by []), to indicate that some field is optional, and add this to the respective field using the @JsonFormat annotation.

For example, take this class:

public class OptionalTimeZoneTest {

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX[ VV]")
    private ZonedDateTime date;

    // getter and setter
}

Note the last part ([ VV]): the pattern inside [] is an optional section, so the parser tries to parse it, if present. And the pattern VV is the zone id (or timezone's name; for more details, take a look at the javadoc)

With this, both formats can be read:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
// add this to preserve the same offset (don't convert to UTC)
mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);

// without timezone
String json = "{ \"date\": \"2016-07-26T05:30:47+01:00\" }";
OptionalTimeZoneTest value = mapper.readValue(json, OptionalTimeZoneTest.class);
System.out.println(value.getDate()); // 2016-07-26T05:30:47+01:00

// with timezone
json = "{ \"date\": \"2016-07-26T05:30:47+01:00 Europe/Paris\" }";
value = mapper.readValue(json, OptionalTimeZoneTest.class);
System.out.println(value.getDate()); // 2016-07-26T05:30:47+02:00[Europe/Paris]

The output is:

2016-07-26T05:30:47+01:00
2016-07-26T05:30:47+02:00[Europe/Paris]

Note that in the first case the output is 2016-07-26T05:30:47+01:00 (because it doesn't have a timezone, so the +01:00 offset is applied).

But in the second case the output is 2016-07-26T05:30:47+02:00[Europe/Paris], because in Europe/Paris timezone, 26/07/2016 is summer-time (so the offset is +02:00). And the java.time API were implemented in a way that the timezone takes precedence when parsing such a String.


If you want all ZonedDateTime instances to be converted to UTC, you can remove this line:

mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);

Without it, the dates will be converted to UTC, and the output will be:

2016-07-26T04:30:47Z[UTC]
2016-07-26T03:30:47Z[UTC]

Upvotes: 6

Related Questions