Search code examples
pythondatetimeattributeerror

Python - datetime.time() comparison returns AttributeError as 'str' object


I'm trying to compare datetime objects in a list to a constant datetime, but I keep getting returned AttributeError: 'str' object has no attribute 'time'

The list: hetero_lst = [datetime.datetime(2021, 2, 8, 6, 45), 'Meeting 1', '45 mins', datetime.datetime(2021, 2, 8, 7, 15), 'Meeting 2', '45 mins', datetime.datetime(2021, 2, 8, 12, 0), 'Meeting 3', '30 mins']

The following...

for element in hetero_lst:
    print(type(element))

...returns:

<class 'datetime.datetime'>
<class 'str'>
<class 'str'>
<class 'datetime.datetime'>
<class 'str'>
<class 'str'>
<class 'datetime.datetime'>
<class 'str'>
<class 'str'>

Here's when I get my AttributeError on line if t2.time() < t1:

t1 = time(hour=10,minute=0,second=0)

for i in reversed(range(len(hetero_lst))):
    t2 = hetero_lst[i]

    if t2.time() < t1:
        print("Deleted item {}".format(t2))
        del t2
    else:
        pass

I really don't get it. Please can someone help?


Solution

  • You get that error because you are trying to call an attribute (in this case a method) .time() on an item in your list of type str, and str-objects does not have any attribute named .time(). To circumvent this you could first check whether the current variable in the list is of type datetime using the method isinstance(t2, datetime), and if so do the other check.

    from datetime import datetime, time
    
    lst = [datetime(2021, 2, 8, 6, 45), 'Meeting 1', '45 mins', datetime(2021, 2, 8, 7, 15), 'Meeting 2', '45 mins', datetime(2021, 2, 8, 12, 0), 'Meeting 3', '30 mins']
    
    t1 = time(hour=10,minute=0,second=0)
    
    for i in reversed(range(len(lst))):
        t2 = lst[i]
        if isinstance(t2, datetime) and t2.time() < t1:
            print("Deleted item {}".format(t2))
            del t2
        else:
            pass
    

    also: The code in your loop won't change the list. The only thing the del t2 does is that it removes the reference to the same memory address as lst[i]. If you would want to actually delete that item in the list, you would have to do it by calling del lst[i] instead. Otherwise, if you print the list after your for-loop above, you'll see that no items are removed.

    A more efficient way of writing that for-loop would be something like below:

    for i, possible_datetime_item in enumerate(lst):
        if isinstance(item, possible_datetime_item) and item.time() < t1:
            print("Deleted item {}".format(possible_datetime_item))
            del lst[i]