def filter_date_range(
        starts, ends, values,
        start_date,
        end_date
        ):
    """ Returns tuple of elements filtered by the specified date range.

    Arguments:
    starts -- start dates (datetime)
    ends -- end dates (datetime)
    values -- glucose values

    start_date -- the earliest date of elements to return
    end_date -- the last date of elements to return

    Output:
    Filtered dates in format (starts, ends, values)
    """
    # ends might not necesarily be the same length as starts/values
    # because not all types have "end dates"
    assert len(starts) == len(values),\
        "expected input shapes to match"

    (filtered_starts,
     filtered_ends,
     filtered_values
     ) = ([], [], [])

    for i in range(0, len(starts)):
        if start_date and ends and ends[i] < start_date:
            continue

        if start_date and not ends and starts[i] < start_date:
            continue

        if end_date and starts[i] > end_date:
            continue

        filtered_starts.append(starts[i])
        filtered_ends.append(ends[i] if ends else None)
        filtered_values.append(values[i])

    assert len(filtered_starts) == len(filtered_ends) == len(filtered_values),\
        "expected output shapes to match"

    return (filtered_starts, filtered_ends, filtered_values)