Skip to content

Commit 183ae5a

Browse files
committed
Supported to parse UTC time with valid zero offset.
Offset format with `+00`, `+0000` and `+00:00` are all supported now.
1 parent 781f3f9 commit 183ae5a

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)