Skip to content

Commit 5bcba32

Browse files
committed
Add 6 hours per year converting from interval
This is the same operation performed by postgres when extracting the number of seconds of an interval: =# select extract(epoch from '1 year'::interval) / 60 / 60 / 24; ?column? ---------- 365.25 This way `extract(epoch from interval)` will match the resulting `timedelta.total_seconds()`. Close #570
1 parent 45f7ec7 commit 5bcba32

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

psycopg/typecast_datetime.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
448448
/* add the days, months years together - they already include a sign */
449449
days += 30 * (PY_LONG_LONG)months + 365 * (PY_LONG_LONG)years;
450450

451+
/* Postgres adds 6 hours for each year, or for each 12 months */
452+
seconds += 6 * 60 * 60 * (PY_LONG_LONG)(years + (months / 12));
453+
451454
return PyObject_CallFunction((PyObject*)PyDateTimeAPI->DeltaType, "LLl",
452455
days, seconds, micros);
453456
}

tests/test_dates.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,32 @@ def test_parse_interval(self):
223223
def test_parse_negative_interval(self):
224224
self._check_interval('-42 days -12:34:56.123456')
225225

226+
def test_parse_mixied_signs_interval(self):
227+
# Intervals in postgres have 4 blocks
228+
# -1 year -2 mons +3 days -04:05:06
229+
# each can be missing, present with no sign, positive, negative
230+
# test all the combos
231+
def cases(s):
232+
return ['', s, '-' + s, '+' + s]
233+
234+
from itertools import product
235+
for parts in product(
236+
cases('1 year'), cases('2 months'),
237+
cases('3 days'), cases('04:05:06')):
238+
s = ' '.join(parts)
239+
if s.isspace():
240+
continue
241+
self._check_interval(s)
242+
243+
def test_parse_interval_element(self):
244+
for i in range(-1000, 1100, 100):
245+
self._check_interval('%s years' % i)
246+
self._check_interval('%s months' % i)
247+
self._check_interval('%s days' % i)
248+
self._check_interval('%s hours' % i)
249+
self._check_interval('%s minutes' % i)
250+
self._check_interval('%s seconds' % i)
251+
226252
def test_parse_infinity(self):
227253
value = self.DATETIME('-infinity', self.curs)
228254
self.assertEqual(str(value), '0001-01-01 00:00:00')

0 commit comments

Comments
 (0)