@@ -433,13 +433,14 @@ def _parse_isoformat_time(tstr):
433
433
434
434
hour , minute , second , microsecond = time_comps
435
435
became_next_day = False
436
+ error_from_components = False
436
437
if (hour == 24 ):
437
- if not all (time_comp == 0 for time_comp in time_comps [1 :]):
438
- raise ValueError ( "minute, second, and microsecond must be 0 when hour is 24" )
439
-
440
- hour = 0
441
- time_comps [ 0 ] = hour
442
- became_next_day = True
438
+ if all (time_comp == 0 for time_comp in time_comps [1 :]):
439
+ hour = 0
440
+ time_comps [ 0 ] = hour
441
+ became_next_day = True
442
+ else :
443
+ error_from_components = True
443
444
444
445
tzi = None
445
446
if tz_pos == len_str and tstr [- 1 ] == 'Z' :
@@ -473,7 +474,7 @@ def _parse_isoformat_time(tstr):
473
474
474
475
time_comps .append (tzi )
475
476
476
- return time_comps , became_next_day
477
+ return time_comps , became_next_day , error_from_components
477
478
478
479
# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar
479
480
def _isoweek_to_gregorian (year , week , day ):
@@ -1881,11 +1882,14 @@ def fromisoformat(cls, date_string):
1881
1882
1882
1883
if tstr :
1883
1884
try :
1884
- time_components , became_next_day = _parse_isoformat_time (tstr )
1885
+ time_components , became_next_day , error_from_components = _parse_isoformat_time (tstr )
1885
1886
except ValueError :
1886
1887
raise ValueError (
1887
1888
f'Invalid isoformat string: { date_string !r} ' ) from None
1888
1889
else :
1890
+ if error_from_components :
1891
+ raise ValueError ("minute, second, and microsecond must be 0 when hour is 24" )
1892
+
1889
1893
if became_next_day :
1890
1894
year , month , day = date_components
1891
1895
# Only wrap day/month when it was previously valid
0 commit comments