【源码阅读】 protobuf 中的 timestamp 包

Timestamp

path: google/protobuf/timestamp.proto
在 timestamppb 中 Timestamp 包含两个字段
seconds 表示秒
nanos 表示纳秒

message Timestamp {
	int64 seconds = 1;
	int32 nanos = 2;
}

timestamp.go

path: github.com/golang/protobuf/ptypes/timestamp.go

package ptypes

import (
	"errors"
	"fmt"
	"time"

	timestamppb "github.com/golang/protobuf/ptypes/timestamp"
)

const (
	// 定义了当前包内方法所支持的最大时间戳和最小时间戳
	// 最小时间开始于 1 年 1 月 1 日 0:0:0 0
	minValidSeconds = -62135596800
	// 最大时间结束于 10000 年 1 月 1 日 0:0:0 0 
	maxValidSeconds = 253402300800
)

// Timestamp 方法将 *timestamppb.Timestamp 类型转换为 time.Time 类型
// 如果参数值为 nil,则返回 time.Unix(0, 0).UTC() 
func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
	var t time.Time
	if ts == nil {
		t = time.Unix(0, 0).UTC() 
	} else {
		t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
	}
	return t, validateTimestamp(ts)
}

// TimestampNow 方法返回一个当前时间的 timestamppb.Timestamp
func TimestampNow() *timestamppb.Timestamp {
	ts, err := TimestampProto(time.Now())
	if err != nil {
		panic("ptypes: time.Now() out of Timestamp range")
	}
	return ts
}

// TimestampProto 方法将 time.Time 类型转换为 *timestamppb.Timestamp 类型
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
	ts := &timestamppb.Timestamp{
		Seconds: t.Unix(),
		Nanos:   int32(t.Nanosecond()),
	}
	if err := validateTimestamp(ts); err != nil {
		return nil, err
	}
	return ts, nil
}

// TimestampString 方法将 *timestamppb.Timestamp 转换为时间字符串
func TimestampString(ts *timestamppb.Timestamp) string {
	t, err := Timestamp(ts)
	if err != nil {
		return fmt.Sprintf("(%v)", err)
	}
	return t.Format(time.RFC3339Nano)
}

// validateTimestamp 方法,判断当前参数是否有效,以下几种场景
// 场景一:为 nil 报错
// 场景二:小于允许最小值,即表示 0001-01-01 以前的时间
// 场景三:大于允许最大值,即表示 10000-01-01 以后的时间
// 场景四:纳秒范围在允许值范围内
func validateTimestamp(ts *timestamppb.Timestamp) error {
	if ts == nil {
		return errors.New("timestamp: nil Timestamp")
	}
	if ts.Seconds < minValidSeconds {
		return fmt.Errorf("timestamp: %v before 0001-01-01", ts)
	}
	if ts.Seconds >= maxValidSeconds {
		return fmt.Errorf("timestamp: %v after 10000-01-01", ts)
	}
	if ts.Nanos < 0 || ts.Nanos >= 1e9 {
		return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts)
	}
	return nil
}

如何使用

请参考:Protobuf 中的 timestamp 与 Go time 的转换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值