Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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?