Skip to content

Commit 414261d

Browse files
authored
Optimize InstantDeserializer replaceZeroOffsetAsZIfNecessary (#266)
1 parent 2722f75 commit 414261d

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,6 @@ public class InstantDeserializer<T extends Temporal>
5454
{
5555
private static final long serialVersionUID = 1L;
5656

57-
/**
58-
* Constants used to check if the time offset is zero. See [jackson-modules-java8#18]
59-
*
60-
* @since 2.9.0
61-
*/
62-
private static final Pattern ISO8601_UTC_ZERO_OFFSET_SUFFIX_REGEX = Pattern.compile("\\+00:?(00)?$");
63-
6457
/**
6558
* Constants used to check if ISO 8601 time string is colonless. See [jackson-modules-java8#131]
6659
*
@@ -226,7 +219,7 @@ public T deserialize(JsonParser parser, DeserializationContext context) throws I
226219
return (T) parser.getEmbeddedObject();
227220

228221
case JsonTokenId.ID_START_ARRAY:
229-
return _deserializeFromArray(parser, context);
222+
return _deserializeFromArray(parser, context);
230223
}
231224
return _handleUnexpectedToken(context, parser, JsonToken.VALUE_STRING,
232225
JsonToken.VALUE_NUMBER_INT, JsonToken.VALUE_NUMBER_FLOAT);
@@ -337,12 +330,37 @@ private ZoneId getZone(DeserializationContext context)
337330
private String replaceZeroOffsetAsZIfNecessary(String text)
338331
{
339332
if (replaceZeroOffsetAsZ) {
340-
return ISO8601_UTC_ZERO_OFFSET_SUFFIX_REGEX.matcher(text).replaceFirst("Z");
333+
return replaceZeroOffsetAsZ(text);
341334
}
342335

343336
return text;
344337
}
345338

339+
private static String replaceZeroOffsetAsZ(String text)
340+
{
341+
int plusIndex = text.lastIndexOf('+');
342+
if (plusIndex < 0) {
343+
return text;
344+
}
345+
int maybeOffsetIndex = plusIndex + 1;
346+
int remaining = text.length() - maybeOffsetIndex;
347+
switch (remaining) {
348+
case 2:
349+
return text.regionMatches(maybeOffsetIndex, "00", 0, remaining)
350+
? text.substring(0, plusIndex) + 'Z'
351+
: text;
352+
case 4:
353+
return text.regionMatches(maybeOffsetIndex, "0000", 0, remaining)
354+
? text.substring(0, plusIndex) + 'Z'
355+
: text;
356+
case 5:
357+
return text.regionMatches(maybeOffsetIndex, "00:00", 0, remaining)
358+
? text.substring(0, plusIndex) + 'Z'
359+
: text;
360+
}
361+
return text;
362+
}
363+
346364
// @since 2.13
347365
private String addInColonToOffsetIfMissing(String text)
348366
{

datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.ISO8601_COLONLESS_OFFSET_REGEX;
2424
import static org.junit.Assert.*;
2525
import static org.junit.Assert.assertNull;
26+
import static org.junit.Assume.assumeTrue;
2627

2728
public class InstantDeserTest extends ModuleTestBase
2829
{
@@ -434,10 +435,43 @@ public void testDeserializationFromStringWithZeroZoneOffset03() throws Exception
434435
assertEquals("The value is not correct.", date, result);
435436
}
436437

438+
@Test
439+
public void testDeserializationFromStringWithZeroZoneOffset04() throws Exception {
440+
assumeInstantCanParseOffsets();
441+
Instant date = Instant.now();
442+
String json = formatWithZeroZoneOffset(date, "+00:30");
443+
Instant result = READER.readValue(json);
444+
assertNotEquals("The value is not correct.", date, result);
445+
}
446+
447+
@Test
448+
public void testDeserializationFromStringWithZeroZoneOffset05() throws Exception {
449+
assumeInstantCanParseOffsets();
450+
Instant date = Instant.now();
451+
String json = formatWithZeroZoneOffset(date, "+01:30");
452+
Instant result = READER.readValue(json);
453+
assertNotEquals("The value is not correct.", date, result);
454+
}
455+
456+
@Test
457+
public void testDeserializationFromStringWithZeroZoneOffset06() throws Exception {
458+
assumeInstantCanParseOffsets();
459+
Instant date = Instant.now();
460+
String json = formatWithZeroZoneOffset(date, "-00:00");
461+
Instant result = READER.readValue(json);
462+
assertEquals("The value is not correct.", date, result);
463+
}
464+
437465
private String formatWithZeroZoneOffset(Instant date, String offset){
438466
return '"' + FORMATTER.format(date).replaceFirst("Z$", offset) + '"';
439467
}
440468

469+
private static void assumeInstantCanParseOffsets() {
470+
// DateTimeFormatter.ISO_INSTANT didn't handle offsets until JDK 12+.
471+
// This was added by https://bugs.openjdk.org/browse/JDK-8166138
472+
assumeTrue(System.getProperty("java.specification.version").compareTo("12") > 0);
473+
}
474+
441475
/*
442476
/**********************************************************************
443477
/* Deserialization, misc other

0 commit comments

Comments
 (0)