def parse_iso_datetime(value: str) -> datetime:
    if (not ISO_8601_DATETIME_REGEX.match(value)):
        raise ValueError(f'passed value {value!r} is not valid ISO-8601 datetime.')
    date_parts = ISO_8601_DATETIME_REGEX.findall(value)[0]
    time_part = date_parts[3]
    if (':' in time_part):
        time_part = time_part.split(':')
    else:
        time_part = list(map(''.join, zip(*([iter(time_part)] * 2))))
    microseconds_part = date_parts[4]
    microseconds = (microseconds_part.lstrip('.') if microseconds_part else '0')
    time_part.append(microseconds)
    if (date_parts[5] and (date_parts[5].lower() != 'z')):
        sign = (1 if (date_parts[5][0] == '+') else (- 1))
        (hours, minutes) = date_parts[5][1:].split(':')
        offset = timezone(timedelta(hours=(int(hours) * sign), minutes=(int(minutes) * sign)))
    elif (date_parts[5] and (date_parts[5].lower() == 'z')):
        offset = timezone.utc
    else:
        offset = None
    return datetime(year=int(date_parts[0]), month=int(date_parts[1]), day=int(date_parts[2]), hour=int(time_part[0]), minute=int(time_part[1]), second=int(time_part[2]), microsecond=int(time_part[3]), tzinfo=offset)
def parse_iso_datetime(value: str) -> datetime:
    if (not ISO_8601_DATETIME_REGEX.match(value)):
        raise ValueError(f'passed value {value!r} is not valid ISO-8601 datetime.')
    date_parts = ISO_8601_DATETIME_REGEX.findall(value)[0]
    time_part = date_parts[3]
    if (':' in time_part):
        time_part = time_part.split(':')
    else:
        time_part = list(map(.join, zip(*([iter(time_part)] * 2))))
    microseconds_part = date_parts[4]
    microseconds = (microseconds_part.lstrip('.') if microseconds_part else '0')
    time_part.append(microseconds)
    if (date_parts[5] and (date_parts[5].lower() != 'z')):
        sign = (1 if (date_parts[5][0] == '+') else (- 1))
        (hours, minutes) = date_parts[5][1:].split(':')
        offset = timezone(timedelta(hours=(int(hours) * sign), minutes=(int(minutes) * sign)))
    elif (date_parts[5] and (date_parts[5].lower() == 'z')):
        offset = timezone.utc
    else:
        offset = None
    return datetime(year=int(date_parts[0]), month=int(date_parts[1]), day=int(date_parts[2]), hour=int(time_part[0]), minute=int(time_part[1]), second=int(time_part[2]), microsecond=int(time_part[3]), tzinfo=offset)