Skip to content

Commit 5610166

Browse files
authored
Merge pull request #84 from graphql-java/update-datetime-scalar-with-spec
Update DateTimeScalar with Custom Scalar specification, add new official specifiedByURL
2 parents 17e7881 + ad7b869 commit 5610166

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

src/main/java/graphql/scalars/datetime/DateTimeScalar.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
2323
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
2424
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
25+
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
2526
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
2627

2728
/**
@@ -95,7 +96,11 @@ public Value<?> valueToLiteral(Object input) {
9596

9697
private OffsetDateTime parseOffsetDateTime(String s, Function<String, RuntimeException> exceptionMaker) {
9798
try {
98-
return OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
99+
OffsetDateTime parse = OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
100+
if (parse.get(OFFSET_SECONDS) == 0 && s.endsWith("-00:00")) {
101+
throw exceptionMaker.apply("Invalid value : '" + s + "'. Negative zero offset is not allowed");
102+
}
103+
return parse;
99104
} catch (DateTimeParseException e) {
100105
throw exceptionMaker.apply("Invalid RFC3339 value : '" + s + "'. because of : '" + e.getMessage() + "'");
101106
}
@@ -104,7 +109,8 @@ private OffsetDateTime parseOffsetDateTime(String s, Function<String, RuntimeExc
104109

105110
INSTANCE = GraphQLScalarType.newScalar()
106111
.name("DateTime")
107-
.description("An RFC-3339 compliant DateTime Scalar")
112+
.description("A slightly refined version of RFC-3339 compliant DateTime Scalar")
113+
.specifiedByUrl("https://scalars.graphql.org/andimarek/date-time") // TODO: Change to .specifiedByURL after release of graphql-java v20
108114
.coercing(coercing)
109115
.build();
110116
}
@@ -124,5 +130,4 @@ private static DateTimeFormatter getCustomDateTimeFormatter() {
124130
.toFormatter();
125131
}
126132

127-
128133
}

src/test/groovy/graphql/scalars/datetime/DateTimeScalarTest.groovy

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package graphql.scalars.datetime
22

33
import graphql.language.StringValue
44
import graphql.scalars.ExtendedScalars
5+
import graphql.schema.CoercingParseLiteralException
56
import graphql.schema.CoercingParseValueException
67
import graphql.schema.CoercingSerializeException
78
import spock.lang.Specification
@@ -28,6 +29,7 @@ class DateTimeScalarTest extends Specification {
2829
"1985-04-12T23:20:50.52Z" | mkOffsetDT("1985-04-12T23:20:50.52Z")
2930
"1996-12-19T16:39:57-08:00" | mkOffsetDT("1996-12-19T16:39:57-08:00")
3031
"1937-01-01T12:00:27.87+00:20" | mkOffsetDT("1937-01-01T12:00:27.87+00:20")
32+
"2022-11-24T01:00:01.02+00:00" | mkOffsetDT("2022-11-24T01:00:01.02+00:00")
3133
mkOffsetDT(year: 1980, hour: 3) | mkOffsetDT("1980-08-08T03:10:09+10:00")
3234
mkZonedDT(year: 1980, hour: 3) | mkOffsetDT("1980-08-08T03:10:09+10:00")
3335
}
@@ -45,6 +47,7 @@ class DateTimeScalarTest extends Specification {
4547
"1996-12-19T16:39:57-08:00" | mkStringValue("1996-12-19T16:39:57.000-08:00")
4648
"1937-01-01T12:00:27.87+00:20" | mkStringValue("1937-01-01T12:00:27.870+00:20")
4749
"1937-01-01T12:00+00:20" | mkStringValue("1937-01-01T12:00:00.000+00:20")
50+
"2022-11-24T01:00:01.02+00:00" | mkStringValue("2022-11-24T01:00:01.020Z")
4851
mkOffsetDT(year: 1980, hour: 3) | mkStringValue("1980-08-08T03:10:09.000+10:00")
4952
mkZonedDT(year: 1980, hour: 3) | mkStringValue("1980-08-08T03:10:09.000+10:00")
5053
}
@@ -59,6 +62,7 @@ class DateTimeScalarTest extends Specification {
5962
where:
6063
input | expectedValue
6164
"1985-04-12" | CoercingParseValueException
65+
"2022-11-24T01:00:01.02-00:00" | CoercingParseValueException
6266
mkLocalDT(year: 1980, hour: 3) | CoercingParseValueException
6367
666 || CoercingParseValueException
6468
}
@@ -85,6 +89,7 @@ class DateTimeScalarTest extends Specification {
8589
"1985-04-12T23:20:50.52Z" | "1985-04-12T23:20:50.520Z"
8690
"1996-12-19T16:39:57-08:00" | "1996-12-19T16:39:57.000-08:00"
8791
"1937-01-01T12:00:27.87+00:20" | "1937-01-01T12:00:27.870+00:20"
92+
"2022-11-24T01:00:01.02+00:00" | "2022-11-24T01:00:01.020Z"
8893
mkOffsetDT(year: 1980, hour: 3) | "1980-08-08T03:10:09.000+10:00"
8994
mkZonedDT(year: 1980, hour: 3) | "1980-08-08T03:10:09.000+10:00"
9095
}
@@ -98,8 +103,21 @@ class DateTimeScalarTest extends Specification {
98103
where:
99104
input | expectedValue
100105
"1985-04-12" | CoercingSerializeException
106+
"2022-11-24T01:00:01.02-00:00" | CoercingSerializeException
101107
mkLocalDT(year: 1980, hour: 3) | CoercingSerializeException
102108
666 || CoercingSerializeException
103109
}
104110

111+
@Unroll
112+
def "datetime parseLiteral bad inputs"() {
113+
114+
when:
115+
coercing.parseLiteral(input)
116+
then:
117+
thrown(expectedValue)
118+
where:
119+
input | expectedValue
120+
"2022-11-24T01:00:01.02-00:00" | CoercingParseLiteralException
121+
}
122+
105123
}

0 commit comments

Comments
 (0)