7

我需要在协议缓冲区消息中序列化一个 .NET DateTime 值。

我的计划是使用 DateTime.ToBinary() 然后在消息中传递 64 位返回值。但我不确定选择什么作为协议缓冲区数据类型来表示它。

我想我对何时应该使用 fixed64(或 sfixed64)数据类型感到困惑。

我假设在这种情况下我会使用带符号的类型,因为 DateTime.ToBinary() 返回的值可以是负数也可以是正数。

4

3 回答 3

9

好吧,您肯定想要int64sfixed64处理正在签名的值。

刚刚做了一个快速测试,DateTime.Now.ToBinary()使用 10 个字节编码,int64sfixed64总是使用 8 个字节。基本上,可变长度编码对于小数字非常有用,但对于大数字来说变得比固定编码更大。(这与使用 UTF-8 而不是 UTF-16 是一种折衷 - ASCII 字符可以在 UTF-8 中以单个字节编码,但后来代码点最终被编码为 2 个字节,然后是 3 个字节,而 UTF -16 总是使用 2 个字节作为 BMP 中的字符。)

我的猜测是DateTime.ToBinary()可能非常大(不知道它究竟做了什么的细节),所以sfixed64更合适。

那有意义吗?

于 2009-05-07T23:31:54.317 回答
4

protobuf-net中,我使用分级方法(实际上,如果您简单地使用它,它会为您处理所有这些DateTime) - 等效的 .proto 是这样的:

message DateTime {
  optional sint64 value = 1; // the offset (in units of the selected scale)
                             // from 1970/01/01
  optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the
                                                     // timespan
  enum TimeSpanScale {
    DAYS = 0;
    HOURS = 1;
    MINUTES = 2;
    SECONDS = 3;
    MILLISECONDS = 4;

    MINMAX = 15; // dubious
  }
}

即,如果DateTime可以用一整天来表示,我只发送自 1970 年以来的天数,等等 - 再加上一个小标记。这意味着可以更有效地发送日期,但对于其他规模而言,它的成本并不高。

就个人而言,我不会使用ToBinary()- 我会明确使用已知时代(例如 unix 时代)的已知比例的偏移量。这使其在平台之间更具可移植性。但是,如果您(例如)仅发送毫秒偏移量,那么固定比例通常比变体长度比例更有效。您是否需要签名或未签名取决于您是否需要时代之前的日期;-p

于 2009-05-08T04:28:06.743 回答
0

您应该使用有符号的 64 位数字,不是因为DateTime可以为负数,而是因为该ToBinary方法返回一个Int64,它是一个有符号的 64 位数字。

于 2009-05-07T23:27:29.057 回答