【问题标题】:Find the closest date from today in a list在列表中查找距今天最近的日期
【发布时间】:2025-07-17 12:05:01
【问题描述】:

我的目标是从列表中获取到今天日期的下一个最接近的日期(在未来,而不是过去)。为简单起见,列表(格式为例如2017-01-31;YYYY-MM-DD)是本赛季的每场足球比赛,我正在尝试创建一个脚本来部分找到“下一场”足球比赛。

我在 Internet 和 Stack Overflow 上搜索了答案并找到了 promising post,但是提供的解决方案使用了不同的格式,当我尝试对其进行定制时,它会触发异常。

我的逻辑包括解析 RSS 提要,所以我只提供原始列表。考虑到这一点,我的简化代码如下:

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

这是我尝试改编上一篇文章的解决方案(我不精通函数式编程,所以我可能没有正确改编它):

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)

不管我的尝试如何(这在我的情况下可能不是最好的,因为它改变了格式并且我需要最终值仍然是YYYY-MM-DD),有没有更简单的方法来做到这一点?我需要下一场比赛(最接近今天)的价值,因为它将继续在我的逻辑中使用。所以回顾一下,我如何才能在我的列表中找到最近的日期,展望未来,从今天开始。感谢您的帮助!

【问题讨论】:

  • 格式会一直是 yyyy-mm-dd 吗?

标签: python python-3.x list datetime lambda


【解决方案1】:

你可以这样做:

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

对于最接近今天的单个日期。

您可以使用相同的函数按距离今天的距离进行排序:

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

从今天起,返回的列表将在几天内越来越远。如果日期在今天之前或之后,则有效。

如果您只想要未来的日期,请过滤掉过去的日期。由于日期字符串是ISO 8601 格式,所以可以按词法比较:

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())

【讨论】:

  • 选项 #3 成功了,因为我正在寻找未来的日期,但肯定会记住其他日期,因为我肯定会找到它们的用途!非常感谢你的帮助!最后一件事:我是否可以将日期硬编码到“今天”部分,这样我就可以确保一切对开发人员来说都是正确的?如果我尝试用 2017-10-27 替换 datetime.date.today() 进行测试,它显然不起作用。是否有一个简单和临时的测试工作?谢谢!
  • 是的。只需使用datetime.datetime.strptime('1941-12-07', "%Y-%m-%d").date() 或您想使用的任何臭名昭著的日期。对于过滤器,只需使用实际的日期字符串而不是 str(datetime.date.today())
【解决方案2】:

首先让我们使用datetime.datetime.strptimedatetime.datetime.date 方法从字符串创建datetime.date 对象,因为datetime.date 对象是有序且更易于使用的:

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

那么让我们过滤掉未来(今天之后)发生的日期

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

然后我们可以使用min简单地找到下一个最接近的日期

next_closest_date = min(future_dates)

这给了我们

>>>next_closest_date
2017-09-01

举个例子


警告

如果今天之后没有日期,这将导致类似的错误

ValueError: min() arg is an empty sequence

如果没问题,我们可以离开它,但如果我们不想出错 - 我们可以为 min 指定默认值,以防像这样的空序列

next_closest_date = min(future_dates, default=None)

最后我们可以写一个函数如下

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)

并像使用它

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)

【讨论】:

  • 另外,如果我按原样运行函数而不做任何修改(这是我的最终意图),我会得到一个“TypeError:不可排序的类型:NoneType()
  • 编辑:所以我发现问题是函数返回中的默认语句。没有它,它会按预期运行。但是,我理解您为什么使用它;有没有一种方法可以解决这个问题而不必取出默认语句?
  • @J.Squillaro:如果需要列表,我们可以使用filter(None, next_closest_dates_with_none_values)list(filter(None, next_closest_dates_with_none_values)) 过滤None 值(因为filter 创建迭代器)