PostgreSQL TIME转google.protobuf.Timestamp出现负值问题解决
解决PostgreSQL TIME类型转google.protobuf.Timestamp的日期范围问题
问题根源:PostgreSQL的TIME类型仅包含时分秒信息,Go的sql包扫描该类型时会默认填充0000-01-01作为日期,而google.protobuf.Timestamp的合法日期范围是0001-01-01至9999-12-31,超出范围导致转换后出现负秒数。
下面提供两种可行的解决方法:
方法一:SQL查询时拼接合法日期
在查询阶段将TIME字段与合法日期(比如当天日期或固定的0001-01-01)拼接为TIMESTAMP,这样扫描到Go的time.Time时日期就在合法范围内:
var ( id string registeredTime time.Time ) // 使用CURRENT_DATE拼接TIME,得到当天日期+原时间的TIMESTAMP _, err := s.builder.Select("id", "CURRENT_DATE + registered_time AS registered_time"). From("user_table"). Where(sq.Eq{"id": r.Id}). QueryRowContext(ctx). Scan(&id, ®isteredTime) if err != nil { return nil, err } return &storage.Result{ ID: id, RegisteredTime: timestamppb.New(registeredTime), }, nil
如果希望固定日期为0001-01-01,可以把CURRENT_DATE换成'0001-01-01'::date。
方法二:Go代码中手动调整日期
直接扫描TIME字段到sql.Time类型(专门对应数据库TIME类型),再手动组合成合法日期的time.Time:
import "database/sql" var ( id string registeredTime sql.Time ) _, err := s.builder.Select("id", "registered_time"). From("user_table"). Where(sq.Eq{"id": r.Id}). QueryRowContext(ctx). Scan(&id, ®isteredTime) if err != nil { return nil, err } // 将TIME与合法的0001-01-01日期组合 validTime := time.Date(1, time.January, 1, registeredTime.Hour(), registeredTime.Minute(), registeredTime.Second(), registeredTime.Nanosecond(), time.UTC) return &storage.Result{ ID: id, RegisteredTime: timestamppb.New(validTime), }, nil
关于可读格式
如果需要前端显示可读的时间(仅时分秒),可以在前端解析Timestamp时,只提取时分秒部分;或者在Go代码中额外返回一个字符串格式的时间字段(如果proto允许扩展)。
内容的提问来源于stack exchange,提问作者devumesh
相关产品推荐
相关产品推荐

