J. Squillaro
J. Squillaro

Reputation: 175

Find the closest date from today in a list

My objective is to get the next closest date (in the future, not past) to today's date from a list. For simplicity's sake, the list (in the format of e.g. 2017-01-31; YYYY-MM-DD) is each football game in the season and I am trying to create a script that in part finds the "next" football game.

I have searched the internet and Stack Overflow for answers and found a promising post, however the solutions provided are using a different format and when I try to tailor it to mine, it trips exceptions.

My logic includes parsing an RSS feed, so I am just going to provide the raw list instead. With this in mind, my simplified code is as follows:

today = str(datetime.date.today())
print(today)

scheduledatelist = ['2017-09-01', '2017-09-09', '2017-09-16', '2017-09-23', '2017-09-30', '2017-10-07', '2017-10-14', '2017-10-21', '2017-10-27', '2017-11-11', '2017-11-18', '2017-11-25']
scheduledatelist = list(reversed(scheduledatelist)) #purpose: to have earliest dates first

This is my attempt at adapting the previous post's solution (I am not well versed in functional programming, so I may not be adapting it right):

get_datetime = lambda s: datetime.datetime.strptime(s, "%Y-%m-%d")
base = get_datetime(today)
later = filter(lambda d: today(d[0]) > today, scheduledatelist)
closest_date = min(later, key = lambda d: today(d[0]))
print(closest_date)

Regardless of my attempt (which may not be the best in my situation as it changes the format and I need the end value to still be YYYY-MM-DD), is there an easier way of doing this? I need that next game (closest to today) value as that will continue on to be used in my logic. So to recap, how can I find the closest date in my list, looking toward the future, from today. Thank you for your help!

Upvotes: 1

Views: 7125

Answers (2)

dawg
dawg

Reputation: 103714

You can do:

min(scheduledatelist, key=lambda s: 
                  datetime.datetime.strptime(s, "%Y-%m-%d").date()-datetime.date.today())

For the single closest date to today.

You can use the same function to sort by distance from today:

sorted(scheduledatelist, key=lambda s: 
              datetime.datetime.strptime(s, "%Y-%m-%d").date()-datetime.date.today())

And the returned list will be in increasing distance in days from today. Works if the dates are before or after today.

If you want only dates in the future, filter out the dates in the past. Since the date strings are in ISO 8601 format, you can compare lexically:

min([d for d in scheduledatelist if d>str(datetime.date.today())], key=lambda s: 
              datetime.datetime.strptime(s, "%Y-%m-%d").date()-datetime.date.today())

Upvotes: 3

Azat Ibrakov
Azat Ibrakov

Reputation: 10953

first of all let's create datetime.date objects from strings using datetime.datetime.strptime and datetime.datetime.date methods since datetime.date objects are ordered and easier to work with:

date_format = '%Y-%m-%d'
dates = [datetime.datetime.strptime(date_string,
                                    date_format).date()

then let's filter out dates that take place in future (after today)

today = datetime.date.today()
future_dates = [date
                for date in dates
                if date >= today]

then we can simply find next closest date using min

next_closest_date = min(future_dates)

which gives us

>>>next_closest_date
2017-09-01

for given example


WARNING

If there is no dates going after today this will cause error like

ValueError: min() arg is an empty sequence

if it's ok then we can leave it, but if we don't want to get errors – we can specify default value for min in case of empty sequence like

next_closest_date = min(future_dates, default=None)

Finally we can write a function as follows

import datetime


# `default` value is returned when there is no future date strings found
def get_next_closest_date(date_strings, date_format, default=None):
    today = datetime.date.today()
    dates = [datetime.datetime.strptime(date_string,
                                        date_format).date()
             for date_string in date_strings]
    future_dates = [date
                    for date in dates
                    if date >= today]
    return min(future_dates, default)

and use it like

scheduledatelist = ['2017-09-01', '2017-09-09', '2017-09-16', '2017-09-23',
                    '2017-09-30', '2017-10-07', '2017-10-14', '2017-10-21',
                    '2017-10-27', '2017-11-11', '2017-11-18', '2017-11-25']
next_closest_date = get_next_closest_date(date_strings=scheduledatelist,
                                          date_format='%Y-%m-%d')
print(next_closest_date)

Upvotes: 2

Related Questions