diff options
| author | Matthew Schinckel <matt@schinckel.net> | 2017-04-13 11:33:35 +0930 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2017-07-03 19:53:19 -0400 |
| commit | 493f7e9e1ed7d68df102de6c5926a55521b145c9 (patch) | |
| tree | 94931916eb01113ac1398b3b083f5e431f052f8e /django/utils/dateparse.py | |
| parent | 684c0a35f620a3754639b4cbadad16b7560b7c41 (diff) | |
Fixed #28076 -- Added support for PostgreSQL's interval format to parse_duration().
Diffstat (limited to 'django/utils/dateparse.py')
| -rw-r--r-- | django/utils/dateparse.py | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/django/utils/dateparse.py b/django/utils/dateparse.py index 48d15d4c1e..ffb37afcdf 100644 --- a/django/utils/dateparse.py +++ b/django/utils/dateparse.py @@ -50,6 +50,20 @@ iso8601_duration_re = re.compile( r'$' ) +# Support PostgreSQL's day-time interval format, e.g. "3 days 04:05:06". The +# year-month and mixed intervals cannot be converted to a timedelta and thus +# aren't accepted. +postgres_interval_re = re.compile( + r'^' + r'(?:(?P<days>-?\d+) (days? ?))?' + r'(?:(?P<sign>[-+])?' + r'(?P<hours>\d+):' + r'(?P<minutes>\d\d):' + r'(?P<seconds>\d\d)' + r'(?:\.(?P<microseconds>\d{1,6}))?' + r')?$' +) + def parse_date(value): """Parse a string and return a datetime.date. @@ -114,17 +128,19 @@ def parse_duration(value): The preferred format for durations in Django is '%d %H:%M:%S.%f'. - Also supports ISO 8601 representation. + Also supports ISO 8601 representation and PostgreSQL's day-time interval + format. """ match = standard_duration_re.match(value) if not match: - match = iso8601_duration_re.match(value) + match = iso8601_duration_re.match(value) or postgres_interval_re.match(value) if match: kw = match.groupdict() + days = datetime.timedelta(float(kw.pop('days', 0) or 0)) sign = -1 if kw.pop('sign', '+') == '-' else 1 if kw.get('microseconds'): kw['microseconds'] = kw['microseconds'].ljust(6, '0') if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'): kw['microseconds'] = '-' + kw['microseconds'] kw = {k: float(v) for k, v in kw.items() if v is not None} - return sign * datetime.timedelta(**kw) + return days + sign * datetime.timedelta(**kw) |
