@@ -51,6 +51,14 @@ public class InstantDeserializer<T extends Temporal>
5151{
5252 private static final long serialVersionUID = 1L ;
5353
54+ /**
55+ * Constants used to check if the time offset is zero
56+ *
57+ * @since 2.9.0
58+ */
59+ private static final String ISO8601_UTC_ZERO_OFFSET_SUFFIX_REGEX = "\\ +00:?(00)?$" ;
60+ private static final String ISO8601_UTC_ZERO_OFFSET_REGEX = "[^\\ +]+" + ISO8601_UTC_ZERO_OFFSET_SUFFIX_REGEX ;
61+
5462 public static final InstantDeserializer <Instant > INSTANT = new InstantDeserializer <>(
5563 Instant .class , DateTimeFormatter .ISO_INSTANT ,
5664 Instant ::from ,
@@ -87,13 +95,13 @@ public class InstantDeserializer<T extends Temporal>
8795 protected final BiFunction <T , ZoneId , T > adjust ;
8896
8997 /**
90- * In case of vanilla `Instant` we seem to need to translate "+0000"
98+ * In case of vanilla `Instant` we seem to need to translate "+0000 | +00:00 | +00 "
9199 * timezone designator into plain "Z" for some reason; see
92100 * [datatype-jsr310#79] for more info
93101 *
94- * @since 2.7.5
102+ * @since 2.9.0
95103 */
96- protected final boolean replace0000AsZ ;
104+ protected final boolean replaceZeroOffsetAsZ ;
97105
98106 /**
99107 * Flag for <code>JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE</code>
@@ -108,14 +116,14 @@ protected InstantDeserializer(Class<T> supportedType,
108116 Function <FromIntegerArguments , T > fromMilliseconds ,
109117 Function <FromDecimalArguments , T > fromNanoseconds ,
110118 BiFunction <T , ZoneId , T > adjust ,
111- boolean replace0000AsZ )
119+ boolean replaceZeroOffsetAsZ )
112120 {
113121 super (supportedType , formatter );
114122 this .parsedToValue = parsedToValue ;
115123 this .fromMilliseconds = fromMilliseconds ;
116124 this .fromNanoseconds = fromNanoseconds ;
117125 this .adjust = adjust == null ? ((d , z ) -> d ) : adjust ;
118- this .replace0000AsZ = replace0000AsZ ;
126+ this .replaceZeroOffsetAsZ = replaceZeroOffsetAsZ ;
119127 _adjustToContextTZOverride = null ;
120128 }
121129
@@ -127,7 +135,7 @@ protected InstantDeserializer(InstantDeserializer<T> base, DateTimeFormatter f)
127135 fromMilliseconds = base .fromMilliseconds ;
128136 fromNanoseconds = base .fromNanoseconds ;
129137 adjust = base .adjust ;
130- replace0000AsZ = (_formatter == DateTimeFormatter .ISO_INSTANT );
138+ replaceZeroOffsetAsZ = (_formatter == DateTimeFormatter .ISO_INSTANT );
131139 _adjustToContextTZOverride = base ._adjustToContextTZOverride ;
132140 }
133141
@@ -139,7 +147,7 @@ protected InstantDeserializer(InstantDeserializer<T> base, Boolean adjustToConte
139147 fromMilliseconds = base .fromMilliseconds ;
140148 fromNanoseconds = base .fromNanoseconds ;
141149 adjust = base .adjust ;
142- replace0000AsZ = base .replace0000AsZ ;
150+ replaceZeroOffsetAsZ = base .replaceZeroOffsetAsZ ;
143151 _adjustToContextTZOverride = adjustToContextTimezoneOverride ;
144152 }
145153
@@ -189,13 +197,8 @@ public T deserialize(JsonParser parser, DeserializationContext context) throws I
189197 // fall through to default handling, to get error there
190198 }
191199 }
192- // 24-May-2016, tatu: as per [datatype-jsr310#79] seems like we need
193- // some massaging in some cases...
194- if (replace0000AsZ ) {
195- if (string .endsWith ("+0000" )) {
196- string = string .substring (0 , string .length () - 5 ) + "Z" ;
197- }
198- }
200+
201+ string = replaceZeroOffsetAsZIfNecessary (string );
199202 }
200203
201204 T value ;
@@ -285,6 +288,20 @@ private ZoneId getZone(DeserializationContext context)
285288 return (_valueClass == Instant .class ) ? null : context .getTimeZone ().toZoneId ();
286289 }
287290
291+ private String replaceZeroOffsetAsZIfNecessary (String text )
292+ {
293+ if (replaceZeroOffsetAsZ && endsWithZeroOffset (text )) {
294+ return text .replaceFirst (ISO8601_UTC_ZERO_OFFSET_SUFFIX_REGEX , "Z" );
295+ }
296+
297+ return text ;
298+ }
299+
300+ private boolean endsWithZeroOffset (String text )
301+ {
302+ return text .matches (ISO8601_UTC_ZERO_OFFSET_REGEX );
303+ }
304+
288305 public static class FromIntegerArguments // since 2.8.3
289306 {
290307 public final long value ;
0 commit comments