我需要在协议缓冲区消息中序列化一个 .NET DateTime 值。
我的计划是使用 DateTime.ToBinary() 然后在消息中传递 64 位返回值。但我不确定选择什么作为协议缓冲区数据类型来表示它。
我想我对何时应该使用 fixed64(或 sfixed64)数据类型感到困惑。
我假设在这种情况下我会使用带符号的类型,因为 DateTime.ToBinary() 返回的值可以是负数也可以是正数。
我需要在协议缓冲区消息中序列化一个 .NET DateTime 值。
我的计划是使用 DateTime.ToBinary() 然后在消息中传递 64 位返回值。但我不确定选择什么作为协议缓冲区数据类型来表示它。
我想我对何时应该使用 fixed64(或 sfixed64)数据类型感到困惑。
我假设在这种情况下我会使用带符号的类型,因为 DateTime.ToBinary() 返回的值可以是负数也可以是正数。
好吧,您肯定想要int64
或sfixed64
处理正在签名的值。
刚刚做了一个快速测试,DateTime.Now.ToBinary()
使用 10 个字节编码,int64
而sfixed64
总是使用 8 个字节。基本上,可变长度编码对于小数字非常有用,但对于大数字来说变得比固定编码更大。(这与使用 UTF-8 而不是 UTF-16 是一种折衷 - ASCII 字符可以在 UTF-8 中以单个字节编码,但后来代码点最终被编码为 2 个字节,然后是 3 个字节,而 UTF -16 总是使用 2 个字节作为 BMP 中的字符。)
我的猜测是DateTime.ToBinary()
值可能非常大(不知道它究竟做了什么的细节),所以sfixed64
更合适。
那有意义吗?
在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
您应该使用有符号的 64 位数字,不是因为DateTime
可以为负数,而是因为该ToBinary
方法返回一个Int64
,它是一个有符号的 64 位数字。