简体   繁体   中英

Comparing dates and finding the closest date to the current date

I'm looking to compare a list of dates with todays date and would like to return the closest one. Ive had various ideas on it but they are seem very convoluted and involve scoring based on how many days diff and taking the smallest diff. But I have no clue how to do this simply any pointers would be appreciated.

import datetime
import re

date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()

for date_ in date_list:
    match = re.match('.*(\d{4})-(\d{2})-(\d{2}).*', date_)
    if match:
        year = match.group(1)
        month = match.group(2)
        day = match.group(3)
        delta = now - datetime.date(int(year), int(month), int(day))
        print(delta)

As I was Waiting EDIT

So I solved this using the below

import datetime
import re

date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()

for date_ in date_list:
    match = re.match('.*(\d{4})-(\d{2})-(\d{2}).*', date_)
    if match:
        year = match.group(1)
        month = match.group(2)
        day = match.group(3)
        delta = now - datetime.date(int(year), int(month), int(day))

dates_range.append(int(delta.days))
days = min(s for s in dates_range)

convert each string into a datetime.date object, then just subtract and get the smallest difference

import datetime
import re

date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]
now = datetime.date.today()

date_list_converted = [datetime.datetime.strptime(each_date, "%Y-%m-%d").date() for each_date in date_list]
differences = [abs(now - each_date) for each_date in date_list_converted]
minimum = min(differences)
closest_date = date_list[differences.index(minimum)]

Using inbuilts

Python's inbuilt datetime module has the functionality to do what you desire.

Let's first take your list of dates and convert it into a list of datetime objects:

from datetime import datetime

date_list = ['2019-02-10', '2018-01-13', '2019-02-8']
datetime_list = [datetime.strptime(date, "%Y-%m-%d") for date in date_list]

Once we have this we can find the difference between those dates and today's date.

today = datetime.today()

date_diffs = [abs(date - today) for date in datetime_list]

Excellent, date_diffs is now a list of datetime.timedelta objects. All that is left is to find the minimum and find which date this represents.

To find the minimum difference it is simple enough to use min(date_diffs) , however, we then want to use this minimum to extract the corresponding closest date. This can be achieved as:

closest_date = date_list[date_diffs.index(min(date_diffs))]

With pandas

If performance is an issue, it may be worth investigating a pandas implementation. Using pandas we can convert your dates to a pandas dataframe:

from datetime import datetime
import pandas as pd

date_list = ['2019-02-10', '2018-01-13', '2019-02-8']
date_df = pd.to_datetime(date_list)

Finally, as in the method using inbuilts we find the differences in the dates and use it to extract the closest date to today.

today = datetime.today()

date_diffs = abs(today - date_df)

closest_date = date_list[date_diffs.argmin()]

The advantage of this method is that we've removed the for loops and so I'd expect this method to be more efficient for large numbers of dates

This converts the strings to a datetime object, then subracts the current date from that and returns the date with the corresponding lowest absolute difference:

import datetime
import re

date_list = ['2019-02-10', '2018-01-13', '2019-02-8',]

numPattern = re.compile("[0-9]+")


def getclosest(dates):
    global numPattern
    now = datetime.date.today()
    diffs = []

    for day in date_list:
        year, month, day = [int(i) for i in re.findall(numPattern, day)]
        currcheck = datetime.date(year, month, day)
        diffs.append(abs(now - currcheck))

    return dates[diffs.index(min(diffs))]

It's by no means the most efficient, but it's semi-elegant and works.

one fast and simple way will be to use bisect algorithm, especially if your date_list is significantly big :

import datetime
from bisect import bisect_left

FMT = '%Y-%m-%d'
date_list = ['2019-02-10', '2018-01-13', '2019-02-8', '2019-02-12']
date_list.sort()


def closest_day_to_now(days):
    """
    Return the closest day form an ordered list of days
    """
    now = datetime.datetime.now()
    left_closest_day_index = bisect_left(days, now.strftime(FMT))

    # check if there is  one greater value
    if len(days) - 1 > left_closest_day_index:

        right_closest_day_index = left_closest_day_index + 1
        right_day = datetime.datetime.strptime(days[right_closest_day_index], FMT)
        left_day = datetime.datetime.strptime(days[left_closest_day_index], FMT)
        closest_day_index = right_closest_day_index if abs(right_day - now) < abs(left_day - now) \
            else left_closest_day_index

    else:
        closest_day_index = left_closest_day_index

    return days[closest_day_index]


print(closest_day_to_now(date_list))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM