Skip to content

Commit 13c2162

Browse files
authored
Merge pull request #59 from deepakhalale/master
Implement variable length seconds fraction to conform with RFC-3339
2 parents 7e554ba + d8d98e8 commit 13c2162

File tree

4 files changed

+99
-25
lines changed

4 files changed

+99
-25
lines changed

core/src/main/java/org/everit/json/schema/internal/DateTimeFormatValidator.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,51 @@
1515
*/
1616
package org.everit.json.schema.internal;
1717

18-
import org.everit.json.schema.FormatValidator;
19-
20-
import java.text.ParseException;
21-
import java.text.SimpleDateFormat;
18+
import java.time.format.DateTimeFormatter;
19+
import java.time.format.DateTimeFormatterBuilder;
20+
import java.time.format.DateTimeParseException;
21+
import java.time.temporal.ChronoField;
22+
import java.util.List;
2223
import java.util.Optional;
2324

25+
import com.google.common.collect.ImmutableList;
26+
import org.everit.json.schema.FormatValidator;
27+
2428
/**
2529
* Implementation of the "date-time" format value.
2630
*/
2731
public class DateTimeFormatValidator implements FormatValidator {
2832

29-
private static final String DATETIME_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssXXX";
33+
private static final List<String> FORMATS_ACCEPTED = ImmutableList.of(
34+
"yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ss.[0-9]{1,9}Z"
35+
);
36+
37+
private static final String PARTIAL_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
38+
39+
private static final String ZONE_OFFSET_PATTERN = "XXX";
40+
41+
private static final DateTimeFormatter FORMATTER;
42+
43+
static {
44+
final DateTimeFormatter secondsFractionFormatter = new DateTimeFormatterBuilder()
45+
.appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
46+
.toFormatter();
3047

31-
private static final String DATETIME_FORMAT_STRING_SECFRAC = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
48+
final DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder()
49+
.appendPattern(PARTIAL_DATETIME_PATTERN)
50+
.appendOptional(secondsFractionFormatter)
51+
.appendPattern(ZONE_OFFSET_PATTERN);
3252

33-
private SimpleDateFormat dateFormat(final String pattern) {
34-
SimpleDateFormat rval = new SimpleDateFormat(pattern);
35-
rval.setLenient(false);
36-
return rval;
53+
FORMATTER = builder.toFormatter();
3754
}
3855

3956
@Override
4057
public Optional<String> validate(final String subject) {
4158
try {
42-
dateFormat(DATETIME_FORMAT_STRING).parse(subject);
59+
FORMATTER.parse(subject);
4360
return Optional.empty();
44-
} catch (ParseException e) {
45-
try {
46-
dateFormat(DATETIME_FORMAT_STRING_SECFRAC).parse(subject);
47-
return Optional.empty();
48-
} catch (ParseException e1) {
49-
return Optional.of(String.format("[%s] is not a valid date-time", subject));
50-
}
61+
} catch (DateTimeParseException e) {
62+
return Optional.of(String.format("[%s] is not a valid date-time. Expected %s", subject, FORMATS_ACCEPTED));
5163
}
5264
}
5365

core/src/test/java/org/everit/json/schema/internal/DefaultFormatValidatorTest.java

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@
1515
*/
1616
package org.everit.json.schema.internal;
1717

18+
import java.util.Optional;
19+
1820
import org.everit.json.schema.FormatValidator;
1921
import org.junit.Assert;
2022
import org.junit.Test;
2123

22-
import java.util.Optional;
23-
2424
public class DefaultFormatValidatorTest {
2525

2626
private static final String THERE_IS_NO_PLACE_LIKE = "127.0.0.1";
2727

2828
private static final String IPV6_ADDR = "2001:db8:85a3:0:0:8a2e:370:7334";
2929

3030
private void assertFailure(final String subject, final FormatValidator format,
31-
final String expectedFailure) {
31+
final String expectedFailure) {
3232
Optional<String> opt = format.validate(subject);
3333
Assert.assertNotNull("the optional is not null", opt);
3434
Assert.assertTrue("failure exists", opt.isPresent());
@@ -44,18 +44,64 @@ private void assertSuccess(final String subject, final FormatValidator format) {
4444
@Test
4545
public void dateTimeExceedingLimits() {
4646
assertFailure("1996-60-999T16:39:57-08:00", new DateTimeFormatValidator(),
47-
"[1996-60-999T16:39:57-08:00] is not a valid date-time");
47+
"[1996-60-999T16:39:57-08:00] is not a valid date-time. Expected [yyyy-MM-dd'T'HH:mm:ssZ, yyyy-MM-dd'T'HH:mm:ss.[0-9]{1,9}Z]");
4848
}
4949

5050
@Test
5151
public void dateTimeFormatFailure() {
5252
assertFailure("2015-03-13T11:00:000", new DateTimeFormatValidator(),
53-
"[2015-03-13T11:00:000] is not a valid date-time");
53+
"[2015-03-13T11:00:000] is not a valid date-time. Expected [yyyy-MM-dd'T'HH:mm:ssZ, yyyy-MM-dd'T'HH:mm:ss.[0-9]{1,9}Z]");
54+
}
55+
56+
@Test
57+
public void dateTimeWithSingleDigitInSecFracSuccess() {
58+
assertSuccess("2015-02-28T11:00:00.1Z", new DateTimeFormatValidator());
59+
}
60+
61+
@Test
62+
public void dateTimeWithTwoDigitsInSecFracSuccess() {
63+
assertSuccess("2015-02-28T11:00:00.12Z", new DateTimeFormatValidator());
64+
}
65+
66+
@Test
67+
public void dateTimeWithThreeDigitsInSecFracSuccess() {
68+
assertSuccess("2015-02-28T11:00:00.123Z", new DateTimeFormatValidator());
69+
}
70+
71+
@Test
72+
public void dateTimeWithFourDigitsInSecFracSuccess() {
73+
assertSuccess("2015-02-28T11:00:00.1234Z", new DateTimeFormatValidator());
74+
}
75+
76+
@Test
77+
public void dateTimeWithFiveDigitsInSecFracSuccess() {
78+
assertSuccess("2015-02-28T11:00:00.12345Z", new DateTimeFormatValidator());
79+
}
80+
81+
@Test
82+
public void dateTimeWithSixDigitsInSecFracSuccess() {
83+
assertSuccess("2015-02-28T11:00:00.123456Z", new DateTimeFormatValidator());
84+
}
85+
86+
@Test
87+
public void dateTimeWithSevenDigitsInSecFracSuccess() {
88+
assertSuccess("2015-02-28T11:00:00.1234567Z", new DateTimeFormatValidator());
89+
}
90+
91+
@Test
92+
public void dateTimeWithEightDigitsInSecFracSuccess() {
93+
assertSuccess("2015-02-28T11:00:00.12345678Z", new DateTimeFormatValidator());
94+
}
95+
96+
@Test
97+
public void dateTimeWithNineDigitsInSecFracSuccess() {
98+
assertSuccess("2015-02-28T11:00:00.123456789Z", new DateTimeFormatValidator());
5499
}
55100

56101
@Test
57-
public void dateTimeSecFracSuccess() {
58-
assertSuccess("2015-02-28T11:00:00.111Z", new DateTimeFormatValidator());
102+
public void dateTimeWithTenDigitsInSecFracFailure() {
103+
assertFailure("2015-02-28T11:00:00.1234567890Z", new DateTimeFormatValidator(),
104+
"[2015-02-28T11:00:00.1234567890Z] is not a valid date-time. Expected [yyyy-MM-dd'T'HH:mm:ssZ, yyyy-MM-dd'T'HH:mm:ss.[0-9]{1,9}Z]");
59105
}
60106

61107
@Test
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"created": {
6+
"type": "string",
7+
"format": "date-time"
8+
}
9+
},
10+
"required": [
11+
"created"
12+
]
13+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"created": "2011-12-03T10:15:30.1Z"
3+
}

0 commit comments

Comments
 (0)