Skip to content

Commit b2a6e03

Browse files
committed
test for incorred deserialization of datetime without milliseconds using the TypeSerializer + fix
1 parent c953e9c commit b2a6e03

2 files changed

Lines changed: 42 additions & 11 deletions

File tree

src/ServiceStack.Text/Common/DateTimeSerializer.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
7171
DateTimeStyles.AdjustToUniversal);
7272

7373
if (dateTimeStr.Length >= XsdDateTimeFormat3F.Length
74-
&& dateTimeStr.Length <= XsdDateTimeFormat.Length)
74+
&& dateTimeStr.Length <= XsdDateTimeFormat.Length
75+
&& dateTimeStr.EndsWith("Z"))
7576
{
7677
#if NETFX_CORE
7778
var dateTimeType = JsConfig.DateHandler != JsonDateHandler.ISO8601
@@ -80,11 +81,7 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
8081

8182
return XmlConvert.ToDateTimeOffset(dateTimeStr, dateTimeType).DateTime.Prepare();
8283
#else
83-
var dateTimeType = JsConfig.DateHandler != JsonDateHandler.ISO8601
84-
? XmlDateTimeSerializationMode.Local
85-
: XmlDateTimeSerializationMode.RoundtripKind;
86-
87-
return XmlConvert.ToDateTime(dateTimeStr, dateTimeType).Prepare();
84+
return XmlConvert.ToDateTime(dateTimeStr, XmlDateTimeSerializationMode.Utc).Prepare();
8885
#endif
8986
}
9087

@@ -190,13 +187,24 @@ public static string ToShortestXsdDateTimeString(DateTime dateTime)
190187
{
191188
var timeOfDay = dateTime.TimeOfDay;
192189

193-
if (timeOfDay.Ticks == 0)
194-
return dateTime.ToString(ShortDateTimeFormat);
190+
string xsdDateTimeString;
195191

196-
if (timeOfDay.Milliseconds == 0)
197-
return dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormatSeconds);
192+
if (timeOfDay.Ticks == 0)
193+
{
194+
xsdDateTimeString = dateTime.ToString(ShortDateTimeFormat);
195+
}
196+
else if (timeOfDay.Milliseconds == 0)
197+
{
198+
xsdDateTimeString = dateTime.Kind != DateTimeKind.Utc
199+
? dateTime.ToString("yyyy-MM-ddTHH:mm:sszzz")
200+
: dateTime.ToString(XsdDateTimeFormatSeconds);
201+
}
202+
else
203+
{
204+
xsdDateTimeString = dateTime.Kind != DateTimeKind.Utc ? dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz") : ToXsdDateTimeString(dateTime);
205+
}
198206

199-
return ToXsdDateTimeString(dateTime);
207+
return xsdDateTimeString;
200208
}
201209

202210

tests/ServiceStack.Text.Tests/Utils/DateTimeSerializerTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,29 @@ public void TestSqlServerDateTime()
111111
Assert.That(result, Is.Not.Null);
112112
}
113113

114+
[Test]
115+
public void DateTimeWithoutMilliseconds_should_always_be_deserialized_correctly_by_TypeSerializer()
116+
{
117+
var dateWithoutMillisecondsUtc = new DateTime(2013, 4, 9, 15, 20, 0, DateTimeKind.Utc);
118+
var dateWithoutMillisecondsLocal = new DateTime(2013, 4, 9, 15, 20, 0, DateTimeKind.Local);
119+
var dateWithoutMillisecondsUnspecified = new DateTime(2013, 4, 9, 15, 20, 0, DateTimeKind.Unspecified);
120+
121+
string serialized = null;
122+
DateTime deserialized;
123+
124+
serialized = TypeSerializer.SerializeToString(dateWithoutMillisecondsUtc);
125+
deserialized = TypeSerializer.DeserializeFromString<DateTime>(serialized);
126+
Assert.AreEqual(dateWithoutMillisecondsUtc, deserialized);
127+
128+
serialized = TypeSerializer.SerializeToString(dateWithoutMillisecondsLocal);
129+
deserialized = TypeSerializer.DeserializeFromString<DateTime>(serialized);
130+
Assert.AreEqual(dateWithoutMillisecondsLocal, deserialized);
131+
132+
serialized = TypeSerializer.SerializeToString(dateWithoutMillisecondsUnspecified);
133+
deserialized = TypeSerializer.DeserializeFromString<DateTime>(serialized);
134+
Assert.AreEqual(dateWithoutMillisecondsUnspecified, deserialized);
135+
}
136+
114137
[Test, Ignore("Don't pre-serialize into Utc")]
115138
public void UtcDateTime_Is_Deserialized_As_Kind_Utc()
116139
{

0 commit comments

Comments
 (0)