Skip to content

Commit ad9c5c8

Browse files
RehanSaeedjoemcbride
authored andcommitted
Added Date, DateTime, DateTimeOffset and TimeSpan Scalar Types (graphql-dotnet#665)
* Use default DateFormatString & IsoDateFormat is already the default. * Add TimeSpanMillisecondsGraphType & TimeSpanMillisecondsGraphType * Fix TimeSpanSecondsGraphType serialize * Fix DateTime to DateTimeOffset conversion * Add TimeSpanSecondsGraphType and TimeSpanMillisecondsGraphType to GraphTypesLookup * Fix SchemaPrinterTests tests * Fix RegisteredInstanceTests tests * Fix MutationTests * Fix SchemaIntrospectionTests * Fix StarWarsIntrospectionTests * Add TimeSpanMillisecondsGraphTypeTests and fix * Fix TimeSpanMillisecondsGraphType TimeSpan parsing * Add DateGraphTypeTests * Remove skipped test * Add DateTimeOffsetGraphTypeTests * Add TimeSpanSecondsGraphTypeTests * Remove tests no longer needed
1 parent db1d684 commit ad9c5c8

22 files changed

+1866
-214
lines changed

src/GraphQL.Tests/Execution/MutationTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Linq;
33
using System.Threading.Tasks;
44
using GraphQL.Types;
@@ -98,7 +98,7 @@ public class DateTimeHolderType : ObjectGraphType
9898
public DateTimeHolderType()
9999
{
100100
Name = "DateTimeHolder";
101-
Field<DateGraphType>("theDateTime");
101+
Field<DateTimeGraphType>("theDateTime");
102102
}
103103
}
104104

@@ -189,7 +189,7 @@ public MutationChange()
189189
Field<DateTimeHolderType>(
190190
"immediatelyChangeTheDateTime",
191191
arguments: new QueryArguments(
192-
new QueryArgument<DateGraphType>
192+
new QueryArgument<DateTimeGraphType>
193193
{
194194
Name = "newDateTime"
195195
}
@@ -205,7 +205,7 @@ public MutationChange()
205205
Field<DateTimeHolderType>(
206206
"promiseToChangeTheDateTime",
207207
arguments: new QueryArguments(
208-
new QueryArgument<DateGraphType>
208+
new QueryArgument<DateTimeGraphType>
209209
{
210210
Name = "newDateTime"
211211
}
@@ -221,7 +221,7 @@ public MutationChange()
221221
Field<DateTimeHolderType>(
222222
"failToChangeTheDateTime",
223223
arguments: new QueryArguments(
224-
new QueryArgument<DateGraphType>
224+
new QueryArgument<DateTimeGraphType>
225225
{
226226
Name = "newDateTime"
227227
}
@@ -237,7 +237,7 @@ public MutationChange()
237237
Field<DateTimeHolderType>(
238238
"promiseAndFailToChangeTheDateTime",
239239
arguments: new QueryArguments(
240-
new QueryArgument<DateGraphType>
240+
new QueryArgument<DateTimeGraphType>
241241
{
242242
Name = "newDateTime"
243243
}
@@ -430,10 +430,10 @@ mutation M {
430430
},
431431
'third': null,
432432
'fourth': {
433-
'theDateTime': ""2017-04-27T20:19:53.123""
433+
'theDateTime': ""2017-04-27T20:19:53.123Z""
434434
},
435435
'fifth': {
436-
'theDateTime': ""2017-05-27T13:19:53.123""
436+
'theDateTime': ""2017-05-27T13:19:53.123Z""
437437
},
438438
'sixth': null
439439
}";

src/GraphQL.Tests/Execution/RegisteredInstanceTests.cs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,35 @@ public void build_nested_type_with_list()
7979
query: root
8080
}
8181
82-
# The `Date` scalar type represents a timestamp provided in UTC. `Date` expects
83-
# timestamps to be formatted in accordance with the
82+
# The `Date` scalar type represents a year, month and day in accordance with the
8483
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
8584
scalar Date
8685
86+
# The `DateTime` scalar type represents a date and time. `DateTime` expects
87+
# timestamps to be formatted in accordance with the
88+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
89+
scalar DateTime
90+
91+
# The `DateTimeOffset` scalar type represents a date, time and offset from UTC.
92+
# `DateTimeOffset` expects timestamps to be formatted in accordance with the
93+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
94+
scalar DateTimeOffset
95+
8796
scalar Decimal
8897
98+
# The `Milliseconds` scalar type represents a period of time represented as the total number of milliseconds.
99+
scalar Milliseconds
100+
89101
type NestedObjType {
90102
intField: Int
91103
}
92104
93105
type root {
94106
listOfObjField: [NestedObjType]
95107
}
108+
109+
# The `Seconds` scalar type represents a period of time represented as the total number of seconds.
110+
scalar Seconds
96111
");
97112
}
98113

@@ -103,20 +118,35 @@ public void build_nested_type_with_non_null()
103118
query: root
104119
}
105120
106-
# The `Date` scalar type represents a timestamp provided in UTC. `Date` expects
107-
# timestamps to be formatted in accordance with the
121+
# The `Date` scalar type represents a year, month and day in accordance with the
108122
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
109123
scalar Date
110124
125+
# The `DateTime` scalar type represents a date and time. `DateTime` expects
126+
# timestamps to be formatted in accordance with the
127+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
128+
scalar DateTime
129+
130+
# The `DateTimeOffset` scalar type represents a date, time and offset from UTC.
131+
# `DateTimeOffset` expects timestamps to be formatted in accordance with the
132+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
133+
scalar DateTimeOffset
134+
111135
scalar Decimal
112136
137+
# The `Milliseconds` scalar type represents a period of time represented as the total number of milliseconds.
138+
scalar Milliseconds
139+
113140
type NestedObjType {
114141
intField: Int
115142
}
116143
117144
type root {
118145
listOfObjField: NestedObjType!
119146
}
147+
148+
# The `Seconds` scalar type represents a period of time represented as the total number of seconds.
149+
scalar Seconds
120150
");
121151
}
122152

@@ -127,20 +157,35 @@ public void build_nested_type_with_base()
127157
query: root
128158
}
129159
130-
# The `Date` scalar type represents a timestamp provided in UTC. `Date` expects
131-
# timestamps to be formatted in accordance with the
160+
# The `Date` scalar type represents a year, month and day in accordance with the
132161
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
133162
scalar Date
134163
164+
# The `DateTime` scalar type represents a date and time. `DateTime` expects
165+
# timestamps to be formatted in accordance with the
166+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
167+
scalar DateTime
168+
169+
# The `DateTimeOffset` scalar type represents a date, time and offset from UTC.
170+
# `DateTimeOffset` expects timestamps to be formatted in accordance with the
171+
# [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.
172+
scalar DateTimeOffset
173+
135174
scalar Decimal
136175
176+
# The `Milliseconds` scalar type represents a period of time represented as the total number of milliseconds.
177+
scalar Milliseconds
178+
137179
type NestedObjType {
138180
intField: Int
139181
}
140182
141183
type root {
142184
listOfObjField: NestedObjType
143185
}
186+
187+
# The `Seconds` scalar type represents a period of time represented as the total number of seconds.
188+
scalar Seconds
144189
");
145190
}
146191

src/GraphQL.Tests/Introspection/IntrospectionResult.cs

Lines changed: 1030 additions & 1 deletion
Large diffs are not rendered by default.

src/GraphQL.Tests/StarWars/StarWarsIntrospectionTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,22 @@ query SchemaIntrospectionQuery {
219219
'name': 'Date',
220220
'kind': 'SCALAR'
221221
},
222+
{
223+
'name': 'DateTime',
224+
'kind': 'SCALAR'
225+
},
226+
{
227+
'name': 'DateTimeOffset',
228+
'kind': 'SCALAR'
229+
},
230+
{
231+
'name': 'Seconds',
232+
'kind': 'SCALAR'
233+
},
234+
{
235+
'name': 'Milliseconds',
236+
'kind': 'SCALAR'
237+
},
222238
{
223239
'name': 'Decimal',
224240
'kind': 'SCALAR'

src/GraphQL.Tests/Types/DateGraphTypeTests.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,32 @@ public class DateGraphTypeTests
1010
{
1111
private readonly DateGraphType _type = new DateGraphType();
1212

13+
[Fact]
14+
public void serialize_local_date_returns_date_only()
15+
{
16+
CultureTestHelper.UseCultures(() =>
17+
{
18+
var date = new DateTime(2000, 1, 2, 3, 4, 5, 6, DateTimeKind.Local);
19+
20+
var actual = _type.Serialize(date);
21+
22+
actual.ShouldBe("2000-01-02");
23+
});
24+
}
25+
26+
[Fact]
27+
public void serialize_utc_date_returns_date_only()
28+
{
29+
CultureTestHelper.UseCultures(() =>
30+
{
31+
var date = new DateTime(2000, 1, 2, 3, 4, 5, 6, DateTimeKind.Utc);
32+
33+
var actual = _type.Serialize(date);
34+
35+
actual.ShouldBe("2000-01-02");
36+
});
37+
}
38+
1339
[Fact]
1440
public void coerces_valid_date()
1541
{
@@ -34,15 +60,6 @@ public void coerces_datetimes_to_utc()
3460
});
3561
}
3662

37-
[Fact(Skip = "Why?")]
38-
public void coerces_integer_to_null()
39-
{
40-
CultureTestHelper.UseCultures(() =>
41-
{
42-
_type.ParseValue(0).ShouldBe(null);
43-
});
44-
}
45-
4663
[Fact]
4764
public void coerces_invalid_string_to_exception()
4865
{
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Globalization;
3+
using GraphQL.Types;
4+
using Shouldly;
5+
using Xunit;
6+
7+
namespace GraphQL.Tests.Types
8+
{
9+
public class DateTimeGraphTypeTests
10+
{
11+
private readonly DateTimeGraphType _type = new DateTimeGraphType();
12+
13+
[Fact]
14+
public void coerces_valid_date()
15+
{
16+
CultureTestHelper.UseCultures(() =>
17+
{
18+
var expected = DateTime.UtcNow;
19+
var input = expected.ToLocalTime().ToString("O", DateTimeFormatInfo.InvariantInfo);
20+
21+
var actual = _type.ParseValue(input);
22+
23+
actual.ShouldBe(expected);
24+
});
25+
}
26+
27+
[Fact]
28+
public void coerces_datetimes_to_utc()
29+
{
30+
CultureTestHelper.UseCultures(() =>
31+
{
32+
((DateTime) _type.ParseValue("2015-11-21T19:59:32.987+0200")).Kind.ShouldBe(
33+
DateTimeKind.Utc);
34+
});
35+
}
36+
37+
[Fact]
38+
public void coerces_invalid_string_to_exception()
39+
{
40+
CultureTestHelper.UseCultures(() =>
41+
{
42+
Assert.Throws<FormatException>(
43+
()=>_type.ParseValue("some unknown date"));
44+
});
45+
}
46+
47+
[Fact]
48+
public void coerces_invalidly_formatted_date_to_exception()
49+
{
50+
CultureTestHelper.UseCultures(() =>
51+
{
52+
Assert.Throws<FormatException>(
53+
()=> _type.ParseValue("Dec 32 2012"));
54+
});
55+
}
56+
57+
[Fact]
58+
public void coerces_iso8601_formatted_string_to_date()
59+
{
60+
CultureTestHelper.UseCultures(() =>
61+
{
62+
_type.ParseValue("2015-12-01T14:15:07.123Z").ShouldBe(
63+
new DateTime(2015, 12, 01, 14, 15, 7) + TimeSpan.FromMilliseconds(123));
64+
});
65+
}
66+
67+
[Fact]
68+
public void coerces_iso8601_string_with_tzone_to_date()
69+
{
70+
CultureTestHelper.UseCultures(() =>
71+
{
72+
_type.ParseValue("2015-11-21T19:59:32.987+0200").ShouldBe(
73+
new DateTime(2015, 11, 21, 17, 59, 32) + TimeSpan.FromMilliseconds(987));
74+
});
75+
}
76+
}
77+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Globalization;
3+
using GraphQL.Types;
4+
using Shouldly;
5+
using Xunit;
6+
7+
namespace GraphQL.Tests.Types
8+
{
9+
public class DateTimeOffsetGraphTypeTests
10+
{
11+
private readonly DateTimeOffsetGraphType _type = new DateTimeOffsetGraphType();
12+
13+
[Fact]
14+
public void coerces_valid_date()
15+
{
16+
CultureTestHelper.UseCultures(() =>
17+
{
18+
var expected = DateTimeOffset.UtcNow;
19+
var input = expected.ToString("O", DateTimeFormatInfo.InvariantInfo);
20+
21+
var actual = _type.ParseValue(input);
22+
23+
actual.ShouldBe(expected);
24+
});
25+
}
26+
27+
[Fact]
28+
public void coerces_invalid_string_to_exception()
29+
{
30+
CultureTestHelper.UseCultures(() =>
31+
{
32+
Assert.Throws<FormatException>(
33+
()=>_type.ParseValue("some unknown date"));
34+
});
35+
}
36+
37+
[Fact]
38+
public void coerces_invalidly_formatted_date_to_exception()
39+
{
40+
CultureTestHelper.UseCultures(() =>
41+
{
42+
Assert.Throws<FormatException>(
43+
()=> _type.ParseValue("Dec 32 2012"));
44+
});
45+
}
46+
47+
[Fact]
48+
public void coerces_iso8601_utc_formatted_string_to_date()
49+
{
50+
CultureTestHelper.UseCultures(() =>
51+
{
52+
_type.ParseValue("2015-12-01T14:15:07.123Z").ShouldBe(
53+
new DateTimeOffset(2015, 12, 01, 14, 15, 7, 123, TimeSpan.Zero));
54+
});
55+
}
56+
57+
[Fact]
58+
public void coerces_iso8601_string_with_tzone_to_date()
59+
{
60+
CultureTestHelper.UseCultures(() =>
61+
{
62+
_type.ParseValue("2015-11-21T19:59:32.987+0200").ShouldBe(
63+
new DateTimeOffset(2015, 11, 21, 19, 59, 32, 987, TimeSpan.FromHours(2)));
64+
});
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)