Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d22ad4b

Browse files
committed
Merge pull request #343 from niltz/master
Add a JsConfig.AssumeUtc
2 parents ba16e4b + 4b92c7e commit d22ad4b

File tree

4 files changed

+78
-11
lines changed

4 files changed

+78
-11
lines changed

src/ServiceStack.Text/Common/DateTimeSerializer.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ public static DateTime ParseWcfJsonDate(string wcfJsonDate)
402402
private static TimeZoneInfo LocalTimeZone = TimeZoneInfo.Local;
403403
public static void WriteWcfJsonDate(TextWriter writer, DateTime dateTime)
404404
{
405+
if (JsConfig.AssumeUtc && dateTime.Kind == DateTimeKind.Unspecified)
406+
{
407+
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
408+
}
409+
405410
if (JsConfig.DateHandler == JsonDateHandler.ISO8601)
406411
{
407412
writer.Write(dateTime.ToString("o", CultureInfo.InvariantCulture));

src/ServiceStack.Text/JsConfig.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public static JsConfigScope With(
4545
Func<string, Type> typeFinder = null,
4646
bool? treatEnumAsInteger = null,
4747
bool? alwaysUseUtc = null,
48+
bool? assumeUtc = null,
4849
bool? escapeUnicode = null,
4950
bool? includePublicFields = null,
5051
int? maxDepth = null,
@@ -67,6 +68,7 @@ public static JsConfigScope With(
6768
TypeFinder = typeFinder ?? sTypeFinder,
6869
TreatEnumAsInteger = treatEnumAsInteger ?? sTreatEnumAsInteger,
6970
AlwaysUseUtc = alwaysUseUtc ?? sAlwaysUseUtc,
71+
AssumeUtc = assumeUtc ?? sAssumeUtc,
7072
EscapeUnicode = escapeUnicode ?? sEscapeUnicode,
7173
IncludePublicFields = includePublicFields ?? sIncludePublicFields,
7274
MaxDepth = maxDepth ?? sMaxDepth,
@@ -382,6 +384,25 @@ public static bool AlwaysUseUtc
382384
}
383385
}
384386

387+
/// <summary>
388+
/// Gets or sets a value indicating if the framework should always assume <see cref="DateTime"/> is in UTC format if Kind is Unspecified.
389+
/// </summary>
390+
private static bool? sAssumeUtc;
391+
public static bool AssumeUtc
392+
{
393+
// obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
394+
get
395+
{
396+
return (JsConfigScope.Current != null ? JsConfigScope.Current.AssumeUtc : null)
397+
?? sAssumeUtc
398+
?? false;
399+
}
400+
set
401+
{
402+
if (!sAssumeUtc.HasValue) sAssumeUtc = value;
403+
}
404+
}
405+
385406
/// <summary>
386407
/// Gets or sets a value indicating if unicode symbols should be serialized as "\uXXXX".
387408
/// </summary>
@@ -510,6 +531,7 @@ public static void Reset()
510531
sTypeFinder = null;
511532
sTreatEnumAsInteger = null;
512533
sAlwaysUseUtc = null;
534+
sAssumeUtc = null;
513535
sEscapeUnicode = null;
514536
sIncludePublicFields = null;
515537
HasSerializeFn = new HashSet<Type>();

src/ServiceStack.Text/JsConfigScope.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public void Dispose()
7272
public bool? EmitLowercaseUnderscoreNames { get; set; }
7373
public bool? ThrowOnDeserializationError { get; set; }
7474
public bool? AlwaysUseUtc { get; set; }
75+
public bool? AssumeUtc { get; set; }
7576
public bool? EscapeUnicode { get; set; }
7677
public bool? PreferInterfaces { get; set; }
7778
public bool? IncludePublicFields { get; set; }

tests/ServiceStack.Text.Tests/JsonTests/JsonDateTimeTests.cs

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,32 @@ public void Can_deserialize_json_date_timestampOffset_withOffset_asUnspecified()
104104
JsConfig.Reset();
105105
}
106106

107-
[Test]
108-
public void Can_deserialize_json_date_timestampOffset_withZeroOffset_asUnspecified()
109-
{
110-
JsConfig.DateHandler = JsonDateHandler.TimestampOffset;
107+
[Test]
108+
public void Can_deserialize_json_date_timestampOffset_withZeroOffset_asUnspecified()
109+
{
110+
JsConfig.DateHandler = JsonDateHandler.TimestampOffset;
111111

112-
const string json = @"""\/Date(785635200000+0000)\/""";
113-
var fromJson = JsonSerializer.DeserializeFromString<DateTime>(json);
112+
const string json = @"""\/Date(785635200000+0000)\/""";
113+
var fromJson = JsonSerializer.DeserializeFromString<DateTime>(json);
114114

115-
var dateTime = new DateTime(1994, 11, 24, 0, 0, 0, DateTimeKind.Unspecified);
116-
Assert.That(fromJson, Is.EqualTo(dateTime));
117-
Assert.That(fromJson.Kind, Is.EqualTo(dateTime.Kind));
118-
JsConfig.Reset();
119-
}
115+
var dateTime = new DateTime(1994, 11, 24, 0, 0, 0, DateTimeKind.Unspecified);
116+
Assert.That(fromJson, Is.EqualTo(dateTime));
117+
Assert.That(fromJson.Kind, Is.EqualTo(dateTime.Kind));
118+
JsConfig.Reset();
119+
}
120+
121+
[Test]
122+
public void Can_serialize_json_date_timestampOffset_unspecified_assume_utc()
123+
{
124+
JsConfig.DateHandler = JsonDateHandler.TimestampOffset;
125+
JsConfig.AssumeUtc = true;
126+
127+
var dateTime = DateTime.Parse("2013-06-14 19:43:37.663");
128+
var ssJson = JsonSerializer.SerializeToString(dateTime);
129+
130+
Assert.That(ssJson, Is.EqualTo(@"""\/Date(1371239017663)\/"""));
131+
JsConfig.Reset();
132+
}
120133

121134
#endregion
122135

@@ -223,6 +236,19 @@ public void Can_deserialize_json_date_dcjsCompatible_unspecified()
223236
Assert.That(fromJson.Kind, Is.EqualTo(DateTimeKind.Local)); // fromBclJson.Kind
224237
JsConfig.Reset();
225238
}
239+
240+
[Test]
241+
public void Can_serialize_json_date_dcjsCompatible_unspecified_assume_utc()
242+
{
243+
JsConfig.DateHandler = JsonDateHandler.DCJSCompatible;
244+
JsConfig.AssumeUtc = true;
245+
246+
var dateTime = DateTime.Parse("2013-06-14 19:43:37.663");
247+
var ssJson = JsonSerializer.SerializeToString(dateTime);
248+
249+
Assert.That(ssJson, Is.EqualTo(@"""\/Date(1371239017663)\/"""));
250+
JsConfig.Reset();
251+
}
226252
#endif
227253
#endregion
228254

@@ -325,6 +351,19 @@ public void Can_deserialize_json_date_iso8601_withOffset_asLocal()
325351
JsConfig.Reset();
326352
}
327353

354+
[Test]
355+
public void Can_serialize_json_date_iso8601_unspecified_assume_utc()
356+
{
357+
JsConfig.DateHandler = JsonDateHandler.ISO8601;
358+
JsConfig.AssumeUtc = true;
359+
360+
var dateTime = DateTime.Parse("2013-06-14 19:43:37.663");
361+
var ssJson = JsonSerializer.SerializeToString(dateTime);
362+
363+
Assert.That(ssJson, Is.EqualTo(@"""2013-06-14T19:43:37.6630000Z"""));
364+
JsConfig.Reset();
365+
}
366+
328367
#endregion
329368

330369
#region ISO-8601 TimeStampOffset Tests

0 commit comments

Comments
 (0)