protobuf-net does not deserialize DateTime.Kind correctly

Viewed 5033

using protobuf-net.dll Version 1.0.0.280

When I deserialize a DateTime (wrapped in an object), the date/time is ok but the DateTime.Kind property is 'Unspecified'

Consider this test case to serialize/deserialize a DateTime.

[TestMethod]
public void TestDateTimeSerialization()
{
    var obj = new DateTimeWrapper {Date = DateTime.UtcNow};
    obj.Date = DateTime.SpecifyKind(obj.Date, DateTimeKind.Utc);
    var serialized = obj.SerializeProto();
    var deserialized = serialized.DeserializeProto<DateTimeWrapper>();
    Assert.AreEqual(DateTimeKind.Utc, deserialized.Date.Kind);
}

public static byte[] SerializeProto<T>(this T item) where T : class
{
    using (var ms = new MemoryStream())
    {
        Serializer.Serialize(ms, item);
        return ms.ToArray();
    }
}

public static T DeserializeProto<T>(this byte[] raw) where T : class, new()
{
    using (var ms = new MemoryStream(raw))
    {
        return Serializer.Deserialize<T>(ms);
    }
}

The Assert fails, the Kind == Unspecified

Addendum

As a result of protobuf-net not serializing this property (see below) one solution is to assume DateTimeKind is equal to Utc when displaying dates on the client side (only where you know it should be UTC of course):

public static DateTime ToDisplayTime(this DateTime utcDateTime, TimeZoneInfo timezone)
{
    if (utcDateTime.Kind != DateTimeKind.Utc)//may be Unspecified due to serialization
        utcDateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Utc);
    DateTime result = TimeZoneInfo.ConvertTime(utcDateTime, timezone);
    return result;
}

This saves you having to assign to each DateTime property on the receiving side.

7 Answers

Starting with protobuf-net 2.2 (see commit), there is a possibility to opt-in to the serialization of DateTime.Kind. You can set a global flag. The corresponding issue on github (still open).

And here is a usage example in connection with NServiceBus.

Disclaimer: This won't help for the old protobuf-net version the OP is referring to, but this is an old question, and may be helpful for others.

Related