Exception from serializer.WriteObject()
The code below fails when the time zone is set to Berlin (+1:00) or beyond.
DateTime Test = new DateTime(); Test = DateTime.MinValue; Person myPerson = new Person("Chris", "Pietschmann"); // Serialize to JSON System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(myPerson.GetType()); MemoryStream ms = new MemoryStream(); serializer.WriteObject(ms, Test); ==========================> Exception thrown here |
The exception thrown by serializer.WriteObject() is:
System.Runtime.Serialization.SerializationException was unhandled Message="DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON." Source="System.ServiceModel.Web" StackTrace: at System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTime(DateTime value) … |
The exception happens from within WriteDateTime() which actually tries to calculate the tickCount using the code below:
long tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks; |
The problem occurs when CurrentTimeZone.GetUtcOffset is > 0 So if I set my time zone to Berlin (+1:00) or beyond, it will return a positive number which means that tickcount will return a negative number since value.Ticks == 0 (minValue), resulting in the exception.
There are probably a couple of workarounds to this issue. They are:
1. If you are using DateTime.MaxValue or DateTime.MinValue as the default values for some DateTime variables then a simple workaround is to define some MaxDefaultDateTime and MinDefaultDateTime values that do not overflow when converted to UTC. An example can be:
static DateTime MaxDefaultDateTime = DateTime.MaxValue.Subtract(TimeSpan.FromHours(12)); static DateTime MinDefaultDateTime = DateTime.MinValue.Add(TimeSpan.FromHours(12)); and for the sake of completeness, you can have a method that ensures all DateTime values are set correctly, something like: static DateTime GetLimitDateTime(DateTime value) { if (value.Kind != DateTimeKind.Utc) { long ticks = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
if (ticks > DateTime.MaxValue.Ticks) { return MaxDefaultDateTime; } if (ticks < DateTime.MinValue.Ticks) { return MinDefaultDateTime; } } return value; } |
2. Another option is to always convert DateTime values to UTC and serialize/de-serialize UTC values:
DateTime now = DateTime.Now.ToUniversalTime(); DateTime max = DateTime.MaxValue.ToUniversalTime(); DateTime min = DateTime.MinValue.ToUniversalTime(); DateTime value = new DateTime(2000, 12, 31, 20, 0, 0, DateTimeKind.Local).ToUniversalTime(); static DateTime GetUTCDateTime(DateTime value) { return value.ToUniversalTime(); } DateTime time = GetUTCDateTime(DateTime.MinValue); |
Written By
Shamik Misra
Support Escalation Engineer, Microsoft Developer Support
Comments
- Anonymous
November 11, 2013
Is there is a fix scheduled to be released for this problem?