How do I sort a list of datetime or date objects?

Question:

How do I sort a list of date and/or datetime objects? The accepted answer here isn’t working for me:

from datetime import datetime,date,timedelta

a=[date.today(), date.today() + timedelta(days=1), date.today() - timedelta(days=1)]
print(a) # [datetime.date(2013, 1, 22), datetime.date(2013, 1, 23), datetime.date(2013, 1, 21)]
a = a.sort()
print(a) # prints 'None'....what???
Asked By: user_78361084

||

Answers:

You’re getting None because list.sort() it operates in-place, meaning that it doesn’t return anything, but modifies the list itself. You only need to call a.sort() without assigning it to a again.

There is a built in function sorted(), which returns a sorted version of the list – a = sorted(a) will do what you want as well.

Answered By: Volatility

If your list contains a list of strings that look like datetime, you can sort them using a datetime parser as key.

For example, to sort lst, you can pass a lambda that parses each string into datetime as key (for a full list of possible formats, see https://strftime.org/).

from datetime import datetime, date
lst = ['02/01/2023 12:25 PM', '01/22/2023 11:00 PM', '12/01/2022 02:23 AM']
sorted_lst = sorted(lst, key=lambda x: datetime.strptime(x, '%m/%d/%Y %I:%M %p'))
# ['12/01/2022 02:23 AM', '01/22/2023 11:00 PM', '02/01/2023 12:25 PM']

# in-place sorting is also possible
lst.sort(key=lambda x: datetime.strptime(x, '%m/%d/%Y %I:%M %p'))

Of course, you can parse them into datetime first and then sort but that would change the type of the items in the list from

new_lst = sorted(datetime.strptime(x, '%m/%d/%Y %I:%M %p') for x in lst)
# [datetime.datetime(2022, 12, 1, 2, 23), datetime.datetime(2023, 1, 22, 23, 0), datetime.datetime(2023, 2, 1, 12, 25)]

If your list is a mixture of date and datetimes, you can normalize them all into datetime objects, and then sort; again, as a key so that the type of the items in the original list doesn’t change.

lst = [datetime(2013, 1, 21, 6, 14, 47), date(2013, 1, 22), date(2013, 1, 21)]
new_lst = sorted(lst, key=lambda x: x if isinstance(x, datetime) else datetime(x.year, x.month, x.day))
# [datetime.date(2013, 1, 21), datetime.datetime(2013, 1, 21, 6, 14, 47), datetime.date(2013, 1, 22)]
Answered By: cottontail
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.