@@ -67,7 +67,8 @@ public class InstantDeserializer<T extends Temporal>
67
67
a -> Instant .ofEpochMilli (a .value ),
68
68
a -> Instant .ofEpochSecond (a .integer , a .fraction ),
69
69
null ,
70
- true // yes, replace zero offset with Z
70
+ true , // yes, replace zero offset with Z
71
+ true // default: yes, normalize ZoneId
71
72
);
72
73
73
74
public static final InstantDeserializer <OffsetDateTime > OFFSET_DATE_TIME = new InstantDeserializer <>(
@@ -76,7 +77,8 @@ public class InstantDeserializer<T extends Temporal>
76
77
a -> OffsetDateTime .ofInstant (Instant .ofEpochMilli (a .value ), a .zoneId ),
77
78
a -> OffsetDateTime .ofInstant (Instant .ofEpochSecond (a .integer , a .fraction ), a .zoneId ),
78
79
(d , z ) -> (d .isEqual (OffsetDateTime .MIN ) || d .isEqual (OffsetDateTime .MAX ) ? d : d .withOffsetSameInstant (z .getRules ().getOffset (d .toLocalDateTime ()))),
79
- true // yes, replace zero offset with Z
80
+ true , // yes, replace zero offset with Z
81
+ true // default: yes, normalize ZoneId
80
82
);
81
83
82
84
public static final InstantDeserializer <ZonedDateTime > ZONED_DATE_TIME = new InstantDeserializer <>(
@@ -85,7 +87,8 @@ public class InstantDeserializer<T extends Temporal>
85
87
a -> ZonedDateTime .ofInstant (Instant .ofEpochMilli (a .value ), a .zoneId ),
86
88
a -> ZonedDateTime .ofInstant (Instant .ofEpochSecond (a .integer , a .fraction ), a .zoneId ),
87
89
ZonedDateTime ::withZoneSameInstant ,
88
- false // keep zero offset and Z separate since zones explicitly supported
90
+ false , // keep zero offset and Z separate since zones explicitly supported
91
+ true // default: yes, normalize ZoneId
89
92
);
90
93
91
94
protected final Function <FromIntegerArguments , T > fromMilliseconds ;
@@ -119,13 +122,21 @@ public class InstantDeserializer<T extends Temporal>
119
122
*/
120
123
protected final Boolean _readTimestampsAsNanosOverride ;
121
124
125
+ /**
126
+ * Flag set from
127
+ * {@link com.fasterxml.jackson.datatype.jsr310.JavaTimeFeature#NORMALIZE_DESERIALIZED_ZONE_ID} to
128
+ * determine whether {@link ZoneId} is to be normalized during deserialization.
129
+ */
130
+ protected final boolean _normalizeZoneId ;
131
+
122
132
protected InstantDeserializer (Class <T > supportedType ,
123
133
DateTimeFormatter formatter ,
124
134
Function <TemporalAccessor , T > parsedToValue ,
125
135
Function <FromIntegerArguments , T > fromMilliseconds ,
126
136
Function <FromDecimalArguments , T > fromNanoseconds ,
127
137
BiFunction <T , ZoneId , T > adjust ,
128
- boolean replaceZeroOffsetAsZ )
138
+ boolean replaceZeroOffsetAsZ ,
139
+ boolean normalizeZoneId )
129
140
{
130
141
super (supportedType , formatter );
131
142
this .parsedToValue = parsedToValue ;
@@ -135,6 +146,7 @@ protected InstantDeserializer(Class<T> supportedType,
135
146
this .replaceZeroOffsetAsZ = replaceZeroOffsetAsZ ;
136
147
this ._adjustToContextTZOverride = null ;
137
148
this ._readTimestampsAsNanosOverride = null ;
149
+ _normalizeZoneId = normalizeZoneId ;
138
150
}
139
151
140
152
@ SuppressWarnings ("unchecked" )
@@ -148,6 +160,7 @@ protected InstantDeserializer(InstantDeserializer<T> base, DateTimeFormatter f)
148
160
replaceZeroOffsetAsZ = (_formatter == DateTimeFormatter .ISO_INSTANT );
149
161
_adjustToContextTZOverride = base ._adjustToContextTZOverride ;
150
162
_readTimestampsAsNanosOverride = base ._readTimestampsAsNanosOverride ;
163
+ _normalizeZoneId = base ._normalizeZoneId ;
151
164
}
152
165
153
166
@ SuppressWarnings ("unchecked" )
@@ -161,6 +174,7 @@ protected InstantDeserializer(InstantDeserializer<T> base, Boolean adjustToConte
161
174
replaceZeroOffsetAsZ = base .replaceZeroOffsetAsZ ;
162
175
_adjustToContextTZOverride = adjustToContextTimezoneOverride ;
163
176
_readTimestampsAsNanosOverride = base ._readTimestampsAsNanosOverride ;
177
+ _normalizeZoneId = base ._normalizeZoneId ;
164
178
}
165
179
166
180
@ SuppressWarnings ("unchecked" )
@@ -174,6 +188,7 @@ protected InstantDeserializer(InstantDeserializer<T> base, DateTimeFormatter f,
174
188
replaceZeroOffsetAsZ = (_formatter == DateTimeFormatter .ISO_INSTANT );
175
189
_adjustToContextTZOverride = base ._adjustToContextTZOverride ;
176
190
_readTimestampsAsNanosOverride = base ._readTimestampsAsNanosOverride ;
191
+ _normalizeZoneId = base ._normalizeZoneId ;
177
192
}
178
193
179
194
/**
@@ -194,6 +209,7 @@ protected InstantDeserializer(InstantDeserializer<T> base,
194
209
replaceZeroOffsetAsZ = base .replaceZeroOffsetAsZ ;
195
210
_adjustToContextTZOverride = adjustToContextTimezoneOverride ;
196
211
_readTimestampsAsNanosOverride = readTimestampsAsNanosOverride ;
212
+ _normalizeZoneId = base ._normalizeZoneId ;
197
213
}
198
214
199
215
@ Override
@@ -364,7 +380,11 @@ private ZoneId getZone(DeserializationContext context)
364
380
// Instants are always in UTC, so don't waste compute cycles
365
381
// Normalizing the zone to prevent discrepancies.
366
382
// See https://github.com/FasterXML/jackson-modules-java8/pull/267 for details
367
- return (_valueClass == Instant .class ) ? null : context .getTimeZone ().toZoneId ().normalized ();
383
+ if (_valueClass == Instant .class ) {
384
+ return null ;
385
+ }
386
+ ZoneId zoneId = context .getTimeZone ().toZoneId ();
387
+ return _normalizeZoneId ? zoneId .normalized () : zoneId ;
368
388
}
369
389
370
390
private String replaceZeroOffsetAsZIfNecessary (String text )
0 commit comments