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

Commit 9fb67a6

Browse files
committed
Optimize DateTimes serialization
1 parent cf87d2f commit 9fb67a6

File tree

7 files changed

+243
-145
lines changed

7 files changed

+243
-145
lines changed

src/ServiceStack.Text.Net40/ServiceStack.Text.Net40.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<AssemblyName>ServiceStack.Text</AssemblyName>
1313
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
1414
<FileAlignment>512</FileAlignment>
15+
<TargetFrameworkProfile />
1516
</PropertyGroup>
1617
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1718
<DebugSymbols>true</DebugSymbols>
@@ -21,6 +22,7 @@
2122
<DefineConstants>TRACE;DEBUG;NET40</DefineConstants>
2223
<ErrorReport>prompt</ErrorReport>
2324
<WarningLevel>4</WarningLevel>
25+
<Prefer32Bit>false</Prefer32Bit>
2426
</PropertyGroup>
2527
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
2628
<DebugType>pdbonly</DebugType>
@@ -29,6 +31,7 @@
2931
<DefineConstants>TRACE;NET40</DefineConstants>
3032
<ErrorReport>prompt</ErrorReport>
3133
<WarningLevel>4</WarningLevel>
34+
<Prefer32Bit>false</Prefer32Bit>
3235
</PropertyGroup>
3336
<ItemGroup>
3437
<Reference Include="System" />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:String x:Key="/Default/FilterSettingsManager/CoverageFilterXml/@EntryValue">&lt;data&gt;&lt;IncludeFilters /&gt;&lt;ExcludeFilters /&gt;&lt;/data&gt;</s:String>
3+
<s:String x:Key="/Default/FilterSettingsManager/AttributeFilterXml/@EntryValue">&lt;data /&gt;</s:String></wpf:ResourceDictionary>

src/ServiceStack.Text/Common/DateTimeSerializer.cs

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
using System;
1414
using System.Globalization;
15+
using System.IO;
16+
using System.Text;
1517
using System.Xml;
1618
using ServiceStack.Text.Json;
1719

@@ -32,6 +34,7 @@ public static class DateTimeSerializer
3234
public const string EscapedWcfJsonSuffix = ")\\/";
3335
public const string WcfJsonPrefix = "/Date(";
3436
public const char WcfJsonSuffix = ')';
37+
public const string UnspecifiedOffset = "-0000";
3538

3639
/// <summary>
3740
/// If AlwaysUseUtc is set to true then convert all DateTime to UTC.
@@ -83,9 +86,9 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
8386
return XmlConvert.ToDateTimeOffset(dateTimeStr, dateTimeType).DateTime.Prepare();
8487
#else
8588
var dateTime = Env.IsMono ? ParseManual(dateTimeStr) : null;
86-
if (dateTime != null)
89+
if (dateTime != null)
8790
return dateTime.Value;
88-
91+
8992
return XmlConvert.ToDateTime(dateTimeStr, XmlDateTimeSerializationMode.Utc).Prepare();
9093
#endif
9194
}
@@ -94,10 +97,10 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
9497
{
9598
return DateTime.Parse(dateTimeStr, null, DateTimeStyles.AssumeLocal).Prepare();
9699
}
97-
catch(FormatException)
100+
catch (FormatException)
98101
{
99102
var manualDate = ParseManual(dateTimeStr);
100-
if (manualDate != null)
103+
if (manualDate != null)
101104
return manualDate.Value;
102105

103106
throw;
@@ -149,7 +152,7 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
149152
int.TryParse(timeParts[1], out min);
150153

151154
var secParts = timeParts[2].Split('.');
152-
int.TryParse(secParts[0], out ss);
155+
int.TryParse(secParts[0], out ss);
153156
if (secParts.Length == 2)
154157
{
155158
var msStr = secParts[1].PadRight(3, '0');
@@ -179,7 +182,7 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
179182
}
180183
else
181184
{
182-
hh = int.Parse(timeOffset.Substring(0,2));
185+
hh = int.Parse(timeOffset.Substring(0, 2));
183186
min = int.Parse(timeOffset.Substring(2));
184187
}
185188

@@ -299,7 +302,7 @@ public static string ToShortestXsdDateTimeString(DateTime dateTime)
299302
return dateTime.Kind != DateTimeKind.Utc
300303
? dateTime.ToString(DateTimeFormatSecondsUtcOffset)
301304
: dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormatSeconds);
302-
305+
303306
return dateTime.Kind != DateTimeKind.Utc
304307
? dateTime.ToString(DateTimeFormatTicksUtcOffset)
305308
: ToXsdDateTimeString(dateTime);
@@ -340,10 +343,10 @@ public static DateTimeOffset ParseWcfJsonDateOffset(string wcfJsonDate)
340343
return unixTime.FromUnixTimeMs();
341344
}
342345

343-
if (JsConfig.DateHandler == JsonDateHandler.DCJSCompatible)
346+
// DCJS ignores the offset and considers it local time if any offset exists
347+
// REVIEW: DCJS shoves offset in a separate field 'offsetMinutes', we have the offset in the format, so shouldn't we use it?
348+
if (JsConfig.DateHandler == JsonDateHandler.DCJSCompatible || timeZone == UnspecifiedOffset)
344349
{
345-
// DCJS ignores the offset and considers it local time if any offset exists
346-
// REVIEW: DCJS shoves offset in a separate field 'offsetMinutes', we have the offset in the format, so shouldn't we use it?
347350
return unixTime.FromUnixTimeMs().ToLocalTime();
348351
}
349352

@@ -385,9 +388,9 @@ public static DateTime ParseWcfJsonDate(string wcfJsonDate)
385388
return unixTime.FromUnixTimeMs();
386389
}
387390

388-
if (JsConfig.DateHandler == JsonDateHandler.DCJSCompatible)
391+
// DCJS ignores the offset and considers it local time if any offset exists
392+
if (JsConfig.DateHandler == JsonDateHandler.DCJSCompatible || timeZone == UnspecifiedOffset)
389393
{
390-
// DCJS ignores the offset and considers it local time if any offset exists
391394
return unixTime.FromUnixTimeMs().ToLocalTime();
392395
}
393396

@@ -396,34 +399,74 @@ public static DateTime ParseWcfJsonDate(string wcfJsonDate)
396399
return new DateTimeOffset(date, offset).DateTime;
397400
}
398401

399-
public static string ToWcfJsonDate(DateTime dateTime)
402+
private static TimeZoneInfo LocalTimeZone = TimeZoneInfo.Local;
403+
public static void WriteWcfJsonDate(TextWriter writer, DateTime dateTime)
400404
{
401405
if (JsConfig.DateHandler == JsonDateHandler.ISO8601)
402406
{
403-
return dateTime.ToString("o", CultureInfo.InvariantCulture);
407+
writer.Write(dateTime.ToString("o", CultureInfo.InvariantCulture));
408+
return;
404409
}
405410

406411
var timestamp = dateTime.ToUnixTimeMs();
407-
var offset = dateTime.Kind == DateTimeKind.Utc
408-
? string.Empty
409-
: TimeZoneInfo.Local.GetUtcOffset(dateTime).ToTimeOffsetString();
412+
string offset = null;
413+
if (dateTime.Kind != DateTimeKind.Utc)
414+
{
415+
if (JsConfig.DateHandler == JsonDateHandler.TimestampOffset && dateTime.Kind == DateTimeKind.Unspecified)
416+
offset = UnspecifiedOffset;
417+
else
418+
offset = LocalTimeZone.GetUtcOffset(dateTime).ToTimeOffsetString();
419+
}
410420

411-
return EscapedWcfJsonPrefix + timestamp + offset + EscapedWcfJsonSuffix;
421+
writer.Write(EscapedWcfJsonPrefix);
422+
writer.Write(timestamp);
423+
if (offset != null)
424+
{
425+
writer.Write(offset);
426+
}
427+
writer.Write(EscapedWcfJsonSuffix);
412428
}
413429

414-
public static string ToWcfJsonDateTimeOffset(DateTimeOffset dateTimeOffset)
430+
public static string ToWcfJsonDate(DateTime dateTime)
431+
{
432+
var sb = new StringBuilder();
433+
using (var writer = new StringWriter(sb))
434+
{
435+
WriteWcfJsonDate(writer, dateTime);
436+
return sb.ToString();
437+
}
438+
}
439+
440+
public static void WriteWcfJsonDateTimeOffset(TextWriter writer, DateTimeOffset dateTimeOffset)
415441
{
416442
if (JsConfig.DateHandler == JsonDateHandler.ISO8601)
417443
{
418-
return dateTimeOffset.ToString("o", CultureInfo.InvariantCulture);
444+
writer.Write(dateTimeOffset.ToString("o", CultureInfo.InvariantCulture));
445+
return;
419446
}
420447

421448
var timestamp = dateTimeOffset.Ticks.ToUnixTimeMs();
422449
var offset = dateTimeOffset.Offset == TimeSpan.Zero
423-
? string.Empty
450+
? null
424451
: dateTimeOffset.Offset.ToTimeOffsetString();
425452

426-
return EscapedWcfJsonPrefix + timestamp + offset + EscapedWcfJsonSuffix;
453+
writer.Write(EscapedWcfJsonPrefix);
454+
writer.Write(timestamp);
455+
if (offset != null)
456+
{
457+
writer.Write(offset);
458+
}
459+
writer.Write(EscapedWcfJsonSuffix);
460+
}
461+
462+
public static string ToWcfJsonDateTimeOffset(DateTimeOffset dateTimeOffset)
463+
{
464+
var sb = new StringBuilder();
465+
using (var writer = new StringWriter(sb))
466+
{
467+
WriteWcfJsonDateTimeOffset(writer, dateTimeOffset);
468+
return sb.ToString();
469+
}
427470
}
428471
}
429472
}

0 commit comments

Comments
 (0)