asyncpg icon indicating copy to clipboard operation
asyncpg copied to clipboard

negative interval encoding issues due to python's timedelta implementation details

Open takeda opened this issue 6 months ago • 1 comments

  • asyncpg version: 0.29.0
  • PostgreSQL version: 16.1
  • Do you use a PostgreSQL SaaS? If so, which? Can you reproduce the issue with a local PostgreSQL install?: this is happening on local PG
  • Python version: 3.11.7
  • Platform:
  • Do you use pgbouncer?: no
  • Did you install asyncpg with pip?: yes
  • If you built asyncpg locally, which version of Cython did you use?:
  • Can the issue be reproduced under both asyncio and uvloop?: yes

Python's timedelta implementation only allows to store negative number of days, hours, minutes, seconds, microseconds are always positive values. So when a negative value smaller than a day is interpreted it is stored in a strange way, example from Python's documentation:

Note that normalization of negative values may be surprising at first. For example:

>>> from datetime import timedelta
>>> d = timedelta(microseconds=-1)
>>> (d.days, d.seconds, d.microseconds)
(-1, 86399, 999999)

https://docs.python.org/3/library/datetime.html?highlight=timedelta#datetime.timedelta

In my particular case when I'm trying to store -3 hours, that's getting translated in python to:

datetime.timedelta(days=-1, seconds=75600)

And ends up stored in postgresql as: "0 years 0 mons -1 days 21 hours 0 mins 0.0 secs"

Is there also a workaround where I can skip timedelta for interval?

takeda avatar Jan 08 '24 05:01 takeda

Is there also a workaround where I can skip timedelta for interval?

You can set up a custom codec. See an example here

elprans avatar Jan 09 '24 17:01 elprans