Fixed -- Optimized django.utils.dateparse functions by using fromisoformat().
@@ -72,8 +72,10 @@ 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:
+ 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)
@@ -87,8 +89,14 @@ 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:
+ 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}
@@ -104,8 +112,10 @@ 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:
+ 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')
@@ -118,8 +128,7 @@ def parse_datetime(value):
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)
+ return datetime.datetime(**kw, tzinfo=tzinfo)
def parse_duration(value):
