Skip to content

Commit

Permalink
Make interval decoding logic match that of psycopg2.
Browse files Browse the repository at this point in the history
asyncpg will now treat 12-month interval increments as 365-day spans,
instead of 12*30 day spans.  This matches psycopg2 interval decoding
logic.

Fixes: #150.
  • Loading branch information
elprans committed Jul 5, 2017
1 parent 1b1893d commit 6b48443
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
12 changes: 10 additions & 2 deletions asyncpg/protocol/codecs/datetime.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,23 @@ cdef interval_decode(ConnectionSettings settings, FastReadBuffer buf):
cdef:
int32_t days
int32_t months
int32_t years
int64_t seconds = 0
uint32_t microseconds = 0

_decode_time(buf, &seconds, &microseconds)
days = hton.unpack_int32(buf.read(4))
months = hton.unpack_int32(buf.read(4))

return datetime.timedelta(days=days + months * 30, seconds=seconds,
microseconds=microseconds)
if months < 0:
years = -<int32_t>(-months // 12)
months = -<int32_t>(-months % 12)
else:
years = <int32_t>(months // 12)
months = <int32_t>(months % 12)

return datetime.timedelta(days=days + months * 30 + years * 365,
seconds=seconds, microseconds=microseconds)


cdef init_datetime_codecs():
Expand Down
13 changes: 13 additions & 0 deletions tests/test_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,19 @@ def test_bitstring(self):

self.assertEqual(len(bits.bytes), expected_bytelen)

async def test_interval(self):
res = await self.con.fetchval("SELECT '5 years'::interval")
self.assertEqual(res, datetime.timedelta(days=1825))

res = await self.con.fetchval("SELECT '5 years 1 month'::interval")
self.assertEqual(res, datetime.timedelta(days=1855))

res = await self.con.fetchval("SELECT '-5 years'::interval")
self.assertEqual(res, datetime.timedelta(days=-1825))

res = await self.con.fetchval("SELECT '-5 years -1 month'::interval")
self.assertEqual(res, datetime.timedelta(days=-1855))

async def test_unhandled_type_fallback(self):
await self.con.execute('''
CREATE EXTENSION IF NOT EXISTS isn
Expand Down

0 comments on commit 6b48443

Please sign in to comment.