在Protocol Buffers和Go语言的time包之间进行Timestamp、Duration和时间类型的互相转换

废弃+的

根据”https://pkg.go.dev/github.com/golang/protobuf/ptypes”上的说明,现在”google.golang.org/protobuf”已经有相应的函数支持,所以应该将本文中的代码迁移到新的函数上。


(以下、原文)

请用中文自然地重新表达以下内容,只需一个选项:
(以下、元の記事)

谷歌最初开发的一种数据序列化格式,叫做协议缓冲(Protocol Buffers),在这篇文章中重新介绍了协议缓冲的接口描述语言(IDL)。

Protobuf 中预先准备了一个被称为 “well-known types” 的常用类型,其中包括日期和时间以及时间段。

    • google.protobuf.Timestamp

 

    google.protobuf.Duration

google.protobuf.Timestamp表示的是不带时区的时间。它可以记录日期、时间和纳秒。时间区被认为是UTC。
google.protobuf.Duration表示的是一段时间。它可以表示秒、小时等概念,并且可以记录纳秒。

在Go语言中,对应这些概念的可以说是标准包time中的time.Time和time.Duration。

当然,由于互相转换的需求,提供了方便的软件包。

時刻型的互轉

tspb.Timestamp → time.Time 时间

使用 github.com/golang/protobuf/ptypes#Timestamp。

func Timestamp(ts *tspb.Timestamp) (time.Time, error)

时间.时间 → *tspb.时间戳

可以使用 `github.com/golang/protobuf/ptypes#TimestampProto`。

func TimestampProto(t time.Time) (*tspb.Timestamp, error)

顺便提一句,还有一些方便的函数,如 func TimestampNow() *tspb.Timestamp,可供使用。无需费心去写 ts, _ := TimestampProto(time.Now()) 这样的代码,就能快速创建当前时间。

在什么情况下会发生错误?

两者都是返回错误的接口。这似乎是由于time.Time和tspb.Timestamp之间微妙的不兼容性引起的。例如,即使在Go的time.Date中输入非常大的数字或负数到年份,它也能正常运行。这意味着它可以处理类似于10亿年未来日期或公元前的过去日期的日期。

func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

在这份链接的protobuf的Timestamp类型中,明确写明可以表示从0001-01-01T00:00:00Z到9999-12-31T23:59:59.999999999Z的范围。

protobuf的目的是在系统之间保持互操作性并交换信息,因此它设置了可以在各种系统中正确处理的范围。例如,MySQL的DateTime类型的上限是9999-12-31 23:59:59。

因此,如果在Go语言中创建超出未来或超过去的time.Time,并尝试将其转换为*tspb.Timestamp,会出现错误。如果直接传递超出范围的*tspb.Timestamp给Timestamp(),也会产生错误。

除了其他一些验证以外,请查看ptypes源代码以获取详细信息。

https://github.com/golang/protobuf/blob/6c65a5562fc06764971b7c5d05c76c75e84bdbf7/ptypes/timestamp.go#L63-L77

尽管如此,由于这种情况通常不会在正常系统中发生,也许不需要特别仔细地处理错误也是可以的。

相互转换的期间类型

durpb.Duration → time.Duration

durpb.Duration → 时长。

github.com/golang/protobuf/ptypes#Duration 的中文释义如下:

func Duration(p *durpb.Duration) (time.Duration, error)

时间间隔 → *durpb.Duration

github.com/golang/protobuf/ptypes#DurationProto的中文意思是什么?

func DurationProto(d time.Duration) *durpb.Duration

在什么情况下会发生错误?

哦。与 timestamp 不同的是,从 time.Duration 转换时不会返回错误。

喔。与 timestamp 不同的是,将时间段从 time.Duration 转换时不会收到错误回应。

对于 protobuf,可以处理的范围被写成大约加减一万年。之所以称其为 “大约” 是因为它只粗略地考虑了闰年等情况。

范围大约是正负10,000年。

我认为时间戳可以持续到一万年,所以我们使Duration能够处理相应的时间。

一方面,Go语言中的time.Duration仅以int64的形式内部保存纳秒。因此,它实际上只能表示约290年左右的范围,远远不如time.Duration的表达能力广泛。

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

*time.Duration → *durpb.Duration没有错误发生,因此也省略了错误判断。

总结

    • 時間系は、Goの標準型とprotobufのwell-known型の相互変換メソッドがあって便利

 

    • 微妙にこれらは互換性のない区間があるため、変換時にエラーが起きうるインターフェースになっている

 

    とはいえ、普通はエラーが起きない気がする。
广告
将在 10 秒后关闭
bannerAds