JungleDiff
JungleDiff

Reputation: 3485

Python/Pandas - Given a specific date, find the previous date in the list

I have a list of dates. And given a specific input date, want to find the previous date in the list. Example is:

my_dates_list = ['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30'].
InputDate = '2019-07-15'

the output should be '2019-06-30' because it is the previous date of the InputDate found in the list. Note that the InputDate is not necessarily found in the my_dates_list.

Another example: if InputDate is '2019-03-01', the output should be 2019-02-28.

Upvotes: 1

Views: 1908

Answers (8)

vladislav timin
vladislav timin

Reputation: 1

A solution using bisect(Python Standard Library):

from bisect import bisect

def get_previous_date(dt: datetime, dates_list: list):
    dt_index = bisect(dates_list, dt)
    return sorted_list[dt_index-1] if dt_index != 0 else dt        

Upvotes: 0

Igor Shangin
Igor Shangin

Reputation: 1

Аnother simple solution. It's not only suitable for dates.

def previous_date(dt: datetime, dates_list: list):
    """ get previous date"""

    dates_list.append(dt)
    sorted_list = sorted(set(dates_list))
    dt_index = sorted_list.index(dt)

    return sorted_list[dt_index-1] if dt_index != 0 else dt

Upvotes: 0

yatu
yatu

Reputation: 88226

One approach could be to subtract the InputDate to each date in the list, find the minimum element (greater than 0) in the list and use it to index my_dates_list:

import datetime as datetime

in_date = datetime.datetime.strptime(InputDate, '%Y-%m-%d')
l = [in_date - datetime.datetime.strptime(i, '%Y-%m-%d') for i in my_dates_list]
# [datetime.timedelta(165), datetime.timedelta(137), datetime.timedelta(106)...
my_dates_list[l.index(min(i for i in l if i>datetime.timedelta(0)))]
# '2019-06-30'

Upvotes: 1

Mark Wang
Mark Wang

Reputation: 2757

Filter the list of dates which is no bigger than InputDate, then take the 'largest' value.

max([x for x in my_dates_list if InputDate >= x])

or

max(my_dates_list, key= lambda x:x if x<=InputDate else '0')

Upvotes: 0

Rakesh
Rakesh

Reputation: 82755

Try using min with a custom key

Ex:

import datetime
my_dates_list = ['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30']
InputDate = datetime.datetime.strptime('2019-07-15', '%Y-%m-%d')

print(min(my_dates_list, key=lambda x: InputDate - datetime.datetime.strptime(x, '%Y-%m-%d')))
# --> 2019-06-30

Upvotes: 0

B.C
B.C

Reputation: 587

A solution using pandas.

import pandas as pd

my_dates_list = ['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30']
test_date = '2019-03-01'

# change to datetime
my_dates_list = pd.to_datetime(my_dates_list)
test_date = pd.to_datetime(test_date)

# get less than test date, sort and take first value
my_dates_list[my_dates_list < test_date].sort_values(ascending=False)[0]

Upvotes: 1

user5431233
user5431233

Reputation: 61

The easiest way is to combine the search of year/month/day and put an if-condition in a while-loop to check if the date is in the list; otherwise, it has to decrease the day maintaining the same month/year. If the search gives out no results, then it has to decrease the month, and eventually the year. It is a brute force solution, but it should work.

Upvotes: 0

I. Schubert
I. Schubert

Reputation: 306

You could convert the strings into datetime objects (for example pd.datetime) and then just find the maximum value that is smaller than the date you are looking for:

import pandas as pd

my_dates_list = ['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30']
InputDate = '2019-07-15'

my_dates_list = pd.to_datetime(my_dates_list)
InputDate = pd.to_datetime(InputDate)

print(max(my_dates_list[my_dates_list<InputDate]))

This returns

2019-06-30 00:00:00

Upvotes: 0

Related Questions