Skip to content

Commit f35ab74

Browse files
kezabellefelixxm
authored andcommitted
Fixed #32892 -- Optimized django.utils.dateparse functions by using fromisoformat().
1 parent 857320e commit f35ab74

File tree

1 file changed

+35
-26
lines changed

1 file changed

+35
-26
lines changed

django/utils/dateparse.py

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ def parse_date(value):
7272
Raise ValueError if the input is well formatted but not a valid date.
7373
Return None if the input isn't well formatted.
7474
"""
75-
match = date_re.match(value)
76-
if match:
77-
kw = {k: int(v) for k, v in match.groupdict().items()}
78-
return datetime.date(**kw)
75+
try:
76+
return datetime.date.fromisoformat(value)
77+
except ValueError:
78+
if match := date_re.match(value):
79+
kw = {k: int(v) for k, v in match.groupdict().items()}
80+
return datetime.date(**kw)
7981

8082

8183
def parse_time(value):
@@ -87,12 +89,18 @@ def parse_time(value):
8789
Return None if the input isn't well formatted, in particular if it
8890
contains an offset.
8991
"""
90-
match = time_re.match(value)
91-
if match:
92-
kw = match.groupdict()
93-
kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
94-
kw = {k: int(v) for k, v in kw.items() if v is not None}
95-
return datetime.time(**kw)
92+
try:
93+
# The fromisoformat() method takes time zone info into account and
94+
# returns a time with a tzinfo component, if possible. However, there
95+
# are no circumstances where aware datetime.time objects make sense, so
96+
# remove the time zone offset.
97+
return datetime.time.fromisoformat(value).replace(tzinfo=None)
98+
except ValueError:
99+
if match := time_re.match(value):
100+
kw = match.groupdict()
101+
kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
102+
kw = {k: int(v) for k, v in kw.items() if v is not None}
103+
return datetime.time(**kw)
96104

97105

98106
def parse_datetime(value):
@@ -104,22 +112,23 @@ def parse_datetime(value):
104112
Raise ValueError if the input is well formatted but not a valid datetime.
105113
Return None if the input isn't well formatted.
106114
"""
107-
match = datetime_re.match(value)
108-
if match:
109-
kw = match.groupdict()
110-
kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
111-
tzinfo = kw.pop('tzinfo')
112-
if tzinfo == 'Z':
113-
tzinfo = utc
114-
elif tzinfo is not None:
115-
offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
116-
offset = 60 * int(tzinfo[1:3]) + offset_mins
117-
if tzinfo[0] == '-':
118-
offset = -offset
119-
tzinfo = get_fixed_timezone(offset)
120-
kw = {k: int(v) for k, v in kw.items() if v is not None}
121-
kw['tzinfo'] = tzinfo
122-
return datetime.datetime(**kw)
115+
try:
116+
return datetime.datetime.fromisoformat(value)
117+
except ValueError:
118+
if match := datetime_re.match(value):
119+
kw = match.groupdict()
120+
kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0')
121+
tzinfo = kw.pop('tzinfo')
122+
if tzinfo == 'Z':
123+
tzinfo = utc
124+
elif tzinfo is not None:
125+
offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
126+
offset = 60 * int(tzinfo[1:3]) + offset_mins
127+
if tzinfo[0] == '-':
128+
offset = -offset
129+
tzinfo = get_fixed_timezone(offset)
130+
kw = {k: int(v) for k, v in kw.items() if v is not None}
131+
return datetime.datetime(**kw, tzinfo=tzinfo)
123132

124133

125134
def parse_duration(value):

0 commit comments

Comments
 (0)