Truncate nanoseconds in EncodeText for Timestamptz and Timestamp
PostgreSQL has microsecond precision. If more than this precision is supplied in the text format it is rounded. This was inconsistent with the binary format. See https://github.com/jackc/pgx/issues/699 for original issue.
This commit is contained in:
+1
-1
@@ -158,7 +158,7 @@ func (src Timestamp) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
|
||||
switch src.InfinityModifier {
|
||||
case None:
|
||||
s = src.Time.Format(pgTimestampFormat)
|
||||
s = src.Time.Truncate(time.Microsecond).Format(pgTimestampFormat)
|
||||
case Infinity:
|
||||
s = "infinity"
|
||||
case NegativeInfinity:
|
||||
|
||||
@@ -32,6 +32,51 @@ func TestTimestampTranscode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestTimestampNanosecondsTruncated(t *testing.T) {
|
||||
tests := []struct {
|
||||
input time.Time
|
||||
expected time.Time
|
||||
}{
|
||||
{time.Date(2020, 1, 1, 0, 0, 0, 999999999, time.UTC), time.Date(2020, 1, 1, 0, 0, 0, 999999000, time.UTC)},
|
||||
{time.Date(2020, 1, 1, 0, 0, 0, 999999001, time.UTC), time.Date(2020, 1, 1, 0, 0, 0, 999999000, time.UTC)},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
{
|
||||
ts := pgtype.Timestamp{Time: tt.input, Status: pgtype.Present}
|
||||
buf, err := ts.EncodeText(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d. EncodeText failed - %v", i, err)
|
||||
}
|
||||
|
||||
ts.DecodeText(nil, buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. DecodeText failed - %v", i, err)
|
||||
}
|
||||
|
||||
if !(ts.Status == pgtype.Present && ts.Time.Equal(tt.expected)) {
|
||||
t.Errorf("%d. EncodeText did not truncate nanoseconds", i)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ts := pgtype.Timestamp{Time: tt.input, Status: pgtype.Present}
|
||||
buf, err := ts.EncodeBinary(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d. EncodeBinary failed - %v", i, err)
|
||||
}
|
||||
|
||||
ts.DecodeBinary(nil, buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. DecodeBinary failed - %v", i, err)
|
||||
}
|
||||
|
||||
if !(ts.Status == pgtype.Present && ts.Time.Equal(tt.expected)) {
|
||||
t.Errorf("%d. EncodeBinary did not truncate nanoseconds", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimestampSet(t *testing.T) {
|
||||
type _time time.Time
|
||||
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ func (src Timestamptz) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
|
||||
switch src.InfinityModifier {
|
||||
case None:
|
||||
s = src.Time.UTC().Format(pgTimestamptzSecondFormat)
|
||||
s = src.Time.UTC().Truncate(time.Microsecond).Format(pgTimestamptzSecondFormat)
|
||||
case Infinity:
|
||||
s = "infinity"
|
||||
case NegativeInfinity:
|
||||
|
||||
@@ -32,6 +32,51 @@ func TestTimestamptzTranscode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestTimestamptzNanosecondsTruncated(t *testing.T) {
|
||||
tests := []struct {
|
||||
input time.Time
|
||||
expected time.Time
|
||||
}{
|
||||
{time.Date(2020, 1, 1, 0, 0, 0, 999999999, time.Local), time.Date(2020, 1, 1, 0, 0, 0, 999999000, time.Local)},
|
||||
{time.Date(2020, 1, 1, 0, 0, 0, 999999001, time.Local), time.Date(2020, 1, 1, 0, 0, 0, 999999000, time.Local)},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
{
|
||||
tstz := pgtype.Timestamptz{Time: tt.input, Status: pgtype.Present}
|
||||
buf, err := tstz.EncodeText(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d. EncodeText failed - %v", i, err)
|
||||
}
|
||||
|
||||
tstz.DecodeText(nil, buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. DecodeText failed - %v", i, err)
|
||||
}
|
||||
|
||||
if !(tstz.Status == pgtype.Present && tstz.Time.Equal(tt.expected)) {
|
||||
t.Errorf("%d. EncodeText did not truncate nanoseconds", i)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
tstz := pgtype.Timestamptz{Time: tt.input, Status: pgtype.Present}
|
||||
buf, err := tstz.EncodeBinary(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("%d. EncodeBinary failed - %v", i, err)
|
||||
}
|
||||
|
||||
tstz.DecodeBinary(nil, buf)
|
||||
if err != nil {
|
||||
t.Errorf("%d. DecodeBinary failed - %v", i, err)
|
||||
}
|
||||
|
||||
if !(tstz.Status == pgtype.Present && tstz.Time.Equal(tt.expected)) {
|
||||
t.Errorf("%d. EncodeBinary did not truncate nanoseconds", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimestamptzSet(t *testing.T) {
|
||||
type _time time.Time
|
||||
|
||||
|
||||
Reference in New Issue
Block a user