diff --git a/datetime/README.md b/datetime/README.md index 3892400e..b53d6ba5 100644 --- a/datetime/README.md +++ b/datetime/README.md @@ -37,6 +37,8 @@ For TimeZone handling, `ADJUST_DATES_TO_CONTEXT_TIME_ZONE` (default: true) speci 'SerializedProvider#getTimeZone()' should be used to adjust Date/Time values on deserialization, even if the value itself contains timezone information. The resultant ZoneId will be [normalized](https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html#normalized--) where applicable. If the value is `OffsetDateTime.MIN` or `OffsetDateTime.MAX`, the Date/Time value will not be adjusted. If disabled, it will only be used if the value itself does not contain any TimeZone information. +On serialization, `ObjectMapper`'s default TimeZone is UTC, but that default is **implicit** (`SerializationConfig.hasExplicitTimeZone()` is false until `ObjectMapper.setTimeZone(...)` or `ObjectWriter.with(TimeZone)` is called). `ZonedDateTime` and `OffsetDateTime` therefore keep the zone already on the value when written as ISO-8601 strings. `SerializationFeature.WRITE_DATES_WITH_CONTEXT_TIME_ZONE` (enabled by default since 2.13) only converts to the mapper TimeZone when that timezone was set explicitly. Calling `mapper.setTimeZone(TimeZone.getTimeZone("UTC"))` is enough to make UTC take effect for those types, except when the value is written with `SerializationFeature.WRITE_DATES_WITH_ZONE_ID` enabled (`ZonedDateTime` then always writes its own zone id) or with a `@JsonFormat` pattern whose formatter already carries a timezone of its own. + Finally, there are two features that apply to array handling. `UNWRAP_SINGLE_VALUE_ARRAYS` (default: false) allows auto-conversion from single-element arrays to non-JSON-array values. If the JSON value contains more than one element in the array, deserialization will still fail. `ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT` (default: false) determines whether empty Array value ("[ ]" in JSON) is accepted as null value for regular POJOs ("beans") with data-binding diff --git a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.java b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.java index 80ede099..e95c8748 100644 --- a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.java +++ b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.java @@ -61,6 +61,11 @@ * local dates and times, periods, durations, zones, and more. All {@code java.time} types * have built-in translation to and from ISO-8601 formats. *

+ * Note that {@code ObjectMapper}'s default TimeZone of UTC is implicit, and as such + * does not override the zone already on {@link ZonedDateTime} and {@link OffsetDateTime} + * values written as ISO-8601 Strings: see + * {@link com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase} for details. + *

* Granularity of timestamps is controlled through the companion features * {@link com.fasterxml.jackson.databind.SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS} and * {@link com.fasterxml.jackson.databind.DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS}. For serialization, timestamps are diff --git a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/InstantSerializerBase.java b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/InstantSerializerBase.java index 81c3ebd8..c33706f9 100644 --- a/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/InstantSerializerBase.java +++ b/datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/InstantSerializerBase.java @@ -42,6 +42,24 @@ /** * Base class for serializers used for {@link java.time.Instant} and * other {@link Temporal} subtypes. + *

+ * When writing ISO-8601 Strings, the context {@link java.util.TimeZone} is applied + * only if all of the following hold: + *

+ * Otherwise the zone (or offset) already on the value being written is retained as-is. */ @SuppressWarnings("serial") public abstract class InstantSerializerBase