与Protobuf一起使用的日期和时间类型


74

我正在考虑使用协议缓冲区在Linux和基于Windows的系统之间进行数据交换。

发送日期/时间(时间戳)值的推荐格式是什么?序列化时,该字段应该很小。

Answers:


47

尽管您不是在说使用哪种语言或需要哪种精度,但我还是建议您使用Unix时间编码为int64。在大多数语言和平台上,它都非常容易处理(对于Windows示例,请参见此处),并且Protobufs将使用varint编码来保持大小较小,而又不会过多限制可表示范围。


17
仅使用4个字节,直到2038年……无法超越
JoelFan 2011年

4
Unix时间仅消耗4个字节,这是一种非常有效的编码。但在2038年之后的日期,它需要超过4个字节
JoelFan

3
Unix时间没有根据占用的字节数来指定,它定义为自纪元以来的秒数。传统上,它已被表示为32位整数,但是当今大多数操作系统都使用64位整数。
JesperE 2011年

10
我的观点是:如果您在protobuf中使用Unix Time,那么您将只使用4个字节...这意味着Unix Time很好....这就是我要说的!
顺便

6
不是5吗?Varint编码。
Hounshell

126

Timestamp从protobuf 3.0开始就有消息类型,这就是在模型中创建消息的方法:

syntax = "proto3";

import "google/protobuf/timestamp.proto";

message MyMessage {
    google.protobuf.Timestamp my_field = 1;
}

timestamp.proto 该文件包含使用时间戳的示例,包括与Linux和Windows程序有关的示例。

示例1:从POSIX计算时间戳time()

Timestamp timestamp;
timestamp.set_seconds(time(NULL));
timestamp.set_nanos(0);

示例2:从POSIX计算时间戳gettimeofday()

struct timeval tv;
gettimeofday(&tv, NULL);

Timestamp timestamp;
timestamp.set_seconds(tv.tv_sec);
timestamp.set_nanos(tv.tv_usec * 1000);

示例3:从Win32计算时间戳GetSystemTimeAsFileTime()

FILETIME ft;
GetSystemTimeAsFileTime(&ft);
UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;

// A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
// is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
Timestamp timestamp;
timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));

那JavaScript呢?
Neurotransmitter

4
不确定是否值得一个完整的答案,但是这个问题会询问时间戳和日期,因此,当您不需要更高的精度时,请考虑使用google.type.Date。
micseydel

1
@micseydel:OP要求一个“小”数据类型。google.type.Date为3个整数,并且比仅发送带有Unix时间戳的int64精度低。除了易于阅读之外,很少有需要使用google.type.Date的情况。当然,Protobuf的二进制格式将尽其所能地将这3个整数组合在一起,但总的来说,如果大小重要,这似乎并不理想。
DoomGoober

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.