db-postgres icon indicating copy to clipboard operation
db-postgres copied to clipboard

Fixes socketry/db-postgres#6 - Parsing of timestamps with microsecond precison

Open cyclotron3k opened this issue 3 years ago • 3 comments

Fixes socketry/db-postgres#6 Postgres can return timestamps with microsecond precision, and db-postgres is failing to handle these well.

This is an attempt to fix that behaviour.

Notes:

  • An invalid timestamp will return a nil (as before), but maybe an explicit raise would be better?
  • Ruby <= 2.6 couldn't handle a timezone of UTC - only +HH:MM format
  • Ruby <= 2.6 can't handle timezones in +HH format (i.e. optional minutes)
  • Ruby <= 2.5 can handle microsecond precision, but typically hides it when testing in irb :/

Types of Changes

  • Bug fix.

Contribution

I tested with the following values (collected from Postgres):

strings = [
    "2022-01-02 12:13:14",
    "2022-01-02 12:13:14-11",
    "2018-09-02 03:39:19+04:30",
    "2020-09-25 03:16:48.648682+00",
    "2022-01-02 12:13:14.123456",
    "2022-01-02 12:13:14.123456+08"
]

And I tested in Ruby 2.3 -> 3.1

cyclotron3k avatar Nov 09 '22 00:11 cyclotron3k

Do you think it makes sense to add tests to prevent regressions?

ioquatix avatar Nov 11 '22 09:11 ioquatix

Do you think it makes sense to add tests to prevent regressions?

Good idea. Just added some.

I could have just written unit tests for the Types, but seeing as your tests already depend on a real db connection, I decided to make use of that, and round-trip the test timestamps via the database to provide some guarantees that what I'm testing is valid.

Happy to swap it out for unit tests though. And let me know if you're not a fan of the indentation/coding style/etc.

cyclotron3k avatar Nov 11 '22 13:11 cyclotron3k

Oh just a thought; infinity, -infinity and null are also values that Postgres can return in a timestamp column.

With the infinities, Sequel raises and exception, and ActiveRecord just returns the strings "infinity" and "-infinity".

Date has the concept of Infinity, but it doesn't seem to be very useful in practice:

irb(main):001:0> require 'date'
=> true
irb(main):002:0> Date::Infinity.new < Date.today
(irb):2:in `<': comparison of Date::Infinity with Date failed (ArgumentError)

cyclotron3k avatar Nov 11 '22 13:11 cyclotron3k