protobuf-net没有正确反序列化DateTime.Kind

wal*_*wal 18 .net c# serialization protobuf-net

使用protobuf-net.dll版本1.0.0.280

当我反序列化DateTime(包裹在一个对象中)时,日期/时间是可以的,但DateTime.Kind属性是'未指定'

考虑这个测试用例来序列化/反序列化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);
    }
}
Run Code Online (Sandbox Code Playgroud)

断言失败,种类== Unspecified

附录

由于protobuf-net没有序列化这个属性(见下文),一个解决方案是DateTimeKind在客户端显示日期时简单地假设等于Utc(只有当你知道它应该是UTC的时候):

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;
}
Run Code Online (Sandbox Code Playgroud)

这样可以节省您必须分配给DateTime接收方的每个属性.

Ben*_*igt 6

protobuf.net必须保持与protobuf二进制格式的兼容性,该格式是为Java日期/时间数据类型设计的.KindJava中没有字段 - >不Kind支持protobuf二进制格式 - > Kind不通过网络传输.或类似的规定.

事实证明,protobuf.net对Ticks字段进行编码(仅限),您将找到代码BclHelpers.cs.

但您可以随意在protobuf消息定义中为此值添加另一个字段.


Mar*_*ell 5

作为扩展到Ben的答案......严格来说,protobuf的没有时间的定义,所以没有什么可保留与兼容性.我很想在v2中添加对此的支持,但遗憾的是每个值会增加2个字节.我还没有考虑这是否可以接受......例如,我可能默认为"未指定",因此只有明确的本地或UTC日期才有值.

  • 通常以UTC格式存储日期.当它们通过线路发送时,protobuf丢失了这些信息("Kind"),这意味着在客户端在其时区显示它将不起作用.我很惊讶没有人遇到过这个问题吗? (2认同)