jackc / pgx

PostgreSQL driver and toolkit for Go
MIT License
9.84k stars 802 forks source link

Difficult to compare time.Time fields #863

Closed thequailman closed 3 years ago

thequailman commented 3 years ago

Hello, when using pgx, I'm seeing odd behavior when comparing time.Time fields of structs read from the database vs set in Go. I think it's related to https://github.com/golang/go/issues/19486, as I'm using the TZ=UTC trick to resolve #789 . This makes my timezones created in Go have a nil time.loc value (pgx has a non-nil time.loc pointing to UTC), causing the comparison to fail even though they're the same times.

I would appreciate it if you can follow through on your proposal to honor the timezone DSN setting (timezone=UTC).

thequailman commented 3 years ago

The ends up being caused by time.Unix parsing the binary time data. It will set time.loc to UTC (even though Go's .UTC() does not, it's nil, same for JSON unmarshaling....) and make the time.Time objects not match. The problem here becomes working with these values with JSON unmarshaling, which parses times as UTC with a nil time.loc and makes the values not match (when comparing structs, .Equal() works fine). I can work around this behavior (using TZ=UTC), by adding .Local() calls to fields where necessary. What a mess.

Hopefully someone finds this helpful, closing.

jackc commented 3 years ago

Are you using Time.Equal?

thequailman commented 3 years ago

Yes, time.Equal works fine, but when I compare structs using reflect.DeepEqual I get the comparison failures.

jackc commented 3 years ago

That's why Time.Equal exists, there can be multiple internal representations of the same instant. From the official Go docs:

See the documentation on the Time type for the pitfalls of using == with Time values; most code should use Equal instead.

thequailman commented 3 years ago

I understand, but I can't use that when comparing structs using reflect.

torkelrogstad commented 3 years ago

This is a major issue for me in trying to migrate from lib/pq to pgx. I extensively use https://github.com/stretchr/testify throughout my test suite, where we compare structs using assert.Equal. This again calls reflect.DeepEqual, and my assertions fail. Would a solution be to not set time.loc when the time zone is UTC, or optionally expose some sort of option for doing this?