Skip to content

Commit 7c533e0

Browse files
Tassilo Singhammermichaelstaib
authored andcommitted
Serialize UTC DateTime as Zulu-Time (#339)
1 parent f128a89 commit 7c533e0

File tree

2 files changed

+118
-10
lines changed

2 files changed

+118
-10
lines changed

src/Types.Tests/Types/DateTimeTypeTests.cs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ namespace HotChocolate.Types
77
public class DateTimeTypeTests
88
{
99
[Fact]
10-
public void Serialize_DateTime()
10+
public void Serialize_Utc_DateTime()
1111
{
1212
// arrange
1313
DateTimeType dateTimeType = new DateTimeType();
1414
DateTime dateTime = new DateTime(
1515
2018, 6, 11, 8, 46, 14, DateTimeKind.Utc);
16-
string expectedValue = "2018-06-11T08:46:14+00:00";
16+
string expectedValue = "2018-06-11T08:46:14.000Z";
1717

1818
// act
1919
string serializedValue = (string)dateTimeType.Serialize(dateTime);
@@ -30,7 +30,7 @@ public void Serialize_DateTimeOffset()
3030
DateTimeOffset dateTime = new DateTimeOffset(
3131
new DateTime(2018, 6, 11, 8, 46, 14),
3232
new TimeSpan(4, 0, 0));
33-
string expectedValue = "2018-06-11T08:46:14+04:00";
33+
string expectedValue = "2018-06-11T08:46:14.000+04:00";
3434

3535
// act
3636
string serializedValue = (string)dateTimeType.Serialize(dateTime);
@@ -94,11 +94,59 @@ public void Deserialize_IsoString_DateTimeOffset()
9494
new TimeSpan(4, 0, 0));
9595

9696
// act
97-
DateTimeOffset serializedValue = (DateTimeOffset)dateTimeType
97+
DateTimeOffset deserializedValue = (DateTimeOffset)dateTimeType
9898
.Deserialize("2018-06-11T08:46:14+04:00");
9999

100100
// assert
101-
Assert.Equal(dateTime, serializedValue);
101+
Assert.Equal(dateTime, deserializedValue);
102+
}
103+
104+
[Fact]
105+
public void Deserialize_ZuluString_DateTimeOffset()
106+
{
107+
// arrange
108+
DateTimeType dateTimeType = new DateTimeType();
109+
DateTimeOffset dateTime = new DateTimeOffset(
110+
new DateTime(2018, 6, 11, 8, 46, 14),
111+
new TimeSpan(0, 0, 0));
112+
113+
// act
114+
DateTimeOffset deserializedValue = (DateTimeOffset)dateTimeType
115+
.Deserialize("2018-06-11T08:46:14.000Z");
116+
117+
// assert
118+
Assert.Equal(dateTime, deserializedValue);
119+
}
120+
121+
[Fact]
122+
public void Deserialize_IsoString_DateTime()
123+
{
124+
// arrange
125+
DateTimeType dateTimeType = new DateTimeType();
126+
DateTime dateTime = new DateTime(2018, 6, 11, 8, 46, 14, DateTimeKind.Unspecified);
127+
128+
// act
129+
DateTime deserializedValue = ((DateTimeOffset)dateTimeType
130+
.Deserialize("2018-06-11T08:46:14+04:00")).DateTime;
131+
132+
// assert
133+
Assert.Equal(dateTime, deserializedValue);
134+
Assert.Equal(DateTimeKind.Unspecified, deserializedValue.Kind);
135+
}
136+
137+
[Fact]
138+
public void Deserialize_ZuluString_DateTime()
139+
{
140+
// arrange
141+
DateTimeType dateTimeType = new DateTimeType();
142+
DateTimeOffset dateTime = new DateTime(2018, 6, 11, 8, 46, 14, DateTimeKind.Utc);
143+
144+
// act
145+
DateTime deserializedValue = ((DateTimeOffset)dateTimeType
146+
.Deserialize("2018-06-11T08:46:14.000Z")).DateTime;
147+
148+
// assert
149+
Assert.Equal(dateTime, deserializedValue);
102150
}
103151

104152
[Fact]
@@ -123,7 +171,7 @@ public void ParseValue_DateTimeOffset()
123171
DateTimeOffset dateTime = new DateTimeOffset(
124172
new DateTime(2018, 6, 11, 8, 46, 14),
125173
new TimeSpan(4, 0, 0));
126-
string expectedLiteralValue = "2018-06-11T08:46:14+04:00";
174+
string expectedLiteralValue = "2018-06-11T08:46:14.000+04:00";
127175

128176
// act
129177
StringValueNode stringLiteral =
@@ -134,13 +182,53 @@ public void ParseValue_DateTimeOffset()
134182
}
135183

136184
[Fact]
137-
public void ParseValue_DateTime()
185+
public void ParseValue_Unspecified_DateTime()
186+
{
187+
// arrange
188+
DateTimeType dateTimeType = new DateTimeType();
189+
DateTime dateTime =
190+
new DateTime(2018, 6, 11, 8, 46, 14, DateTimeKind.Unspecified);
191+
DateTimeOffset offset = dateTime;
192+
DateTime offsetDateTime = offset.DateTime;
193+
194+
// act
195+
StringValueNode stringLiteral =
196+
(StringValueNode)dateTimeType.ParseValue(dateTime);
197+
StringValueNode stringLiteralOffset =
198+
(StringValueNode)dateTimeType.ParseValue(offsetDateTime);
199+
200+
// assert
201+
Assert.Equal(stringLiteralOffset, stringLiteral);
202+
}
203+
204+
[Fact]
205+
public void ParseValue_Local_DateTime()
206+
{
207+
// arrange
208+
DateTimeType dateTimeType = new DateTimeType();
209+
DateTime dateTime =
210+
new DateTime(2018, 6, 11, 8, 46, 14, DateTimeKind.Local);
211+
DateTimeOffset offset = dateTime;
212+
DateTime offsetDateTime = offset.DateTime;
213+
214+
// act
215+
StringValueNode stringLiteral =
216+
(StringValueNode)dateTimeType.ParseValue(dateTime);
217+
StringValueNode stringLiteralOffset =
218+
(StringValueNode)dateTimeType.ParseValue(offsetDateTime);
219+
220+
// assert
221+
Assert.Equal(stringLiteral, stringLiteralOffset);
222+
}
223+
224+
[Fact]
225+
public void ParseValue_Utc_DateTime()
138226
{
139227
// arrange
140228
DateTimeType dateTimeType = new DateTimeType();
141229
DateTime dateTime =
142230
new DateTime(2018, 6, 11, 8, 46, 14, DateTimeKind.Utc);
143-
string expectedLiteralValue = "2018-06-11T08:46:14+00:00";
231+
string expectedLiteralValue = "2018-06-11T08:46:14.000Z";
144232

145233
// act
146234
StringValueNode stringLiteral =

src/Types/Types/Scalars/DateTimeType.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using HotChocolate.Language;
34

45
namespace HotChocolate.Types
@@ -18,17 +19,36 @@ public DateTimeType()
1819

1920
protected override string Serialize(DateTime value)
2021
{
21-
return value.ToString("yyyy-MM-ddTHH\\:mm\\:sszzz");
22+
if (value.Kind == DateTimeKind.Utc)
23+
{
24+
return value.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffZ");
25+
}
26+
27+
return value.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffzzz");
2228
}
2329

2430
protected override string Serialize(DateTimeOffset value)
2531
{
26-
return value.ToString("yyyy-MM-ddTHH\\:mm\\:sszzz");
32+
if (value.Offset == TimeSpan.Zero)
33+
{
34+
return value.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffZ");
35+
}
36+
37+
return value.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffzzz");
2738
}
2839

2940
protected override bool TryParseLiteral(
3041
StringValueNode literal, out object obj)
3142
{
43+
if (literal.Value != null && literal.Value.EndsWith("Z"))
44+
{
45+
if (DateTime.TryParse(literal.Value, null as IFormatProvider, DateTimeStyles.AssumeUniversal, out DateTime zDateTime))
46+
{
47+
obj = new DateTimeOffset(zDateTime);
48+
return true;
49+
}
50+
}
51+
3252
if (DateTimeOffset.TryParse(literal.Value, out DateTimeOffset dateTime))
3353
{
3454
obj = dateTime;

0 commit comments

Comments
 (0)