summaryrefslogtreecommitdiff
path: root/django/utils/dateparse.py
diff options
context:
space:
mode:
authorKeryn Knight <keryn@kerynknight.com>2021-07-01 12:05:41 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-07-06 08:57:17 +0200
commitf35ab74752adb37138112657c1bc8b91f50e799b (patch)
tree9344a4811ad72c8d7538cf40aa677f5bf7aa9de9 /django/utils/dateparse.py
parent857320e9e0d9e914c5fbd68e23877ac72675d234 (diff)
downloaddjango-f35ab74752adb37138112657c1bc8b91f50e799b.tar.gz
Fixed #32892 -- Optimized django.utils.dateparse functions by using fromisoformat().
Diffstat (limited to 'django/utils/dateparse.py')
-rw-r--r--django/utils/dateparse.py61
1 files changed, 35 insertions, 26 deletions
diff --git a/django/utils/dateparse.py b/django/utils/dateparse.py
index 47791b9331..60840933d5 100644
--- a/django/utils/dateparse.py
+++ b/django/utils/dateparse.py
@@ -72,10 +72,12 @@ def parse_date(value):
Raise ValueError if the input is well formatted but not a valid date.
Return None if the input isn't well formatted.
"""
- match = date_re.match(value)
- if match:
- kw = {k: int(v) for k, v in match.groupdict().items()}
- return datetime.date(**kw)
+ try:
+ return datetime.date.fromisoformat(value)
+ except ValueError:
+ if match := date_re.match(value):
+ kw = {k: int(v) for k, v in match.groupdict().items()}
+ return datetime.date(**kw)
def parse_time(value):
@@ -87,12 +89,18 @@ def parse_time(value):
Return None if the input isn't well formatted, in particular if it
contains an offset.
"""
- match = time_re.match(value)
- if match:
- kw = match.groupdict()
- kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
- kw = {k: int(v) for k, v in kw.items() if v is not None}
- return datetime.time(**kw)
+ try:
+ # The fromisoformat() method takes time zone info into account and
+ # returns a time with a tzinfo component, if possible. However, there
+ # are no circumstances where aware datetime.time objects make sense, so
+ # remove the time zone offset.
+ return datetime.time.fromisoformat(value).replace(tzinfo=None)
+ except ValueError:
+ if match := time_re.match(value):
+ kw = match.groupdict()
+ kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
+ kw = {k: int(v) for k, v in kw.items() if v is not None}
+ return datetime.time(**kw)
def parse_datetime(value):
@@ -104,22 +112,23 @@ def parse_datetime(value):
Raise ValueError if the input is well formatted but not a valid datetime.
Return None if the input isn't well formatted.
"""
- match = datetime_re.match(value)
- if match:
- kw = match.groupdict()
- kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
- tzinfo = kw.pop('tzinfo')
- if tzinfo == 'Z':
- tzinfo = utc
- elif tzinfo is not None:
- offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
- offset = 60 * int(tzinfo[1:3]) + offset_mins
- if tzinfo[0] == '-':
- offset = -offset
- tzinfo = get_fixed_timezone(offset)
- kw = {k: int(v) for k, v in kw.items() if v is not None}
- kw['tzinfo'] = tzinfo
- return datetime.datetime(**kw)
+ try:
+ return datetime.datetime.fromisoformat(value)
+ except ValueError:
+ if match := datetime_re.match(value):
+ kw = match.groupdict()
+ kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
+ tzinfo = kw.pop('tzinfo')
+ if tzinfo == 'Z':
+ tzinfo = utc
+ elif tzinfo is not None:
+ offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
+ offset = 60 * int(tzinfo[1:3]) + offset_mins
+ if tzinfo[0] == '-':
+ offset = -offset
+ tzinfo = get_fixed_timezone(offset)
+ kw = {k: int(v) for k, v in kw.items() if v is not None}
+ return datetime.datetime(**kw, tzinfo=tzinfo)
def parse_duration(value):