打印日期范围之间的所有星期四

Print all thursdays between date range

我想打印这些日期范围内的所有星期四

from datetime import date, timedelta
sdate = date(2015, 1, 7)   # start date
edate = date(2015, 12, 31)   # end date

最好的 pythonic 方法是什么?

import datetime
import calendar

def weekday_count(start, end, day):
    start_date  = datetime.datetime.strptime(start, '%d/%m/%Y')
    end_date    = datetime.datetime.strptime(end, '%d/%m/%Y')
    day_count = []
    
    for i in range((end_date - start_date).days):
        if calendar.day_name[(start_date + datetime.timedelta(days=i+1)).weekday()] == day:
            print(str(start_date + datetime.timedelta(days=i+1)).split()[0])

weekday_count("01/01/2017", "31/01/2017", "Thursday")

# prints result
# 2017-01-05
# 2017-01-12
# 2017-01-19
# 2017-01-26

使用您的 sdate.weekday() # returns int between 0 (mon) and 6 (sun):

sdate = ...
while sdate < edate:
    if sdate.weekday() != 3:  # not thursday
        sdate += timedelta(days=1)
        continue
    # It is thursday
    print(sdate)
    sdate += timedelta(days=7)  #  next week

简单的解决方案:

from datetime import date, timedelta

sdate = date(2015, 1, 7)   # start date
edate = date(2015, 12, 31)   # end date

delta = edate - sdate

for day in range(delta.days + 1):
    day_obj = sdate + timedelta(days=day)
    if day_obj.weekday() == 3:  # Thursday
        print(day_obj)

# 2015-01-08
# 2015-01-15
# ...
# 2015-12-24
# 2015-12-31

最有效的解决方案:

from datetime import date, timedelta

sdate = date(2015, 1, 7)   # start date
edate = date(2015, 12, 31)   # end date

day_index = 3  # Thursday
delta = (day_index - sdate.weekday()) % 7
match = sdate + timedelta(days=delta)

while match <= edate:  # Change this to `<` to ignore the last one
    print(match) # Can be easily converted to a generator with `yield`
    match += timedelta(days=7)

# 2015-01-08
# 2015-01-15
# ...
# 2015-12-24
# 2015-12-31

文档:

您可以尝试使用列表理解来获取两个日期之间的星期四。

此代码实际上将日期输出为格式化字符串,但您可以通过删除 strftime.

来获取实际日期
from datetime import date, timedelta
sdate = date(2015, 1, 7)   # start date
edate = date(2015, 12, 31)   # end date

thursdays = [(sdate+timedelta(days=d)).strftime('%A %Y-%m-%d') for d in range(0, (edate-sdate).days+1) 
             if (sdate+timedelta(days=d)).weekday() ==3]

print('\n'.join(thursdays))

""" Example output
Thursday 2015-01-08
Thursday 2015-01-15
Thursday 2015-01-22
Thursday 2015-01-29
Thursday 2015-02-05
Thursday 2015-02-12
""""

计算从开始日期到星期四的天数:

days_to_thursday = (3 - sdate.weekday()) % 7

计算两个日期之间的星期四数:

week_diff = ((edate - sdate).days - days_to_thursday ) // 7

获取日期范围内的所有星期四:

thursdays = [sdate + timedelta(days=days_to_thursday + 7 * more_weeks) \
    for more_weeks in range(week_diff + 1) ]

如果需要请打印它们:

for t in thursdays:
    print(t)

大多数人每天都在迭代,这是一种浪费。也可能有助于延迟计算星期四,直到您真正需要它们。为此,您可以使用生成器。

def get_days(start, day_index, end=None):
    # set the start as the next valid day
    start += timedelta(days=(day_index - start.weekday()) % 7)
    week = timedelta(days=7)
    while end and start < end or not end:
        yield start
        start += week

这会延迟到第二天,直到您需要它,如果您不指定和结束日期,则允许无限天。

thursday_generator = get_days(date(2015, 1, 7), 3, date(2015, 12, 31))
print(list(thursday_generator))

"""
[datetime.date(2015, 1, 8), datetime.date(2015, 1, 15), datetime.date(2015, 1, 22), ...]
"""

您可以轻松转储为字符串:

print("\n".join(map(str, thursday_generator)))

"""
2015-01-08
2015-01-15
2015-01-22
...
"""

您还可以使用 f-strings 进行自定义字符串格式设置:

print("\n".join(f"{day:%A %x}" for day in thursday_generator))

"""
Thursday 01/08/15
Thursday 01/15/15
Thursday 01/22/15
...
"""

如果您不指定结束日期,它将永远持续下去。

In [28]: thursday_generator = get_days(date(2015, 1, 7), 3)
    ...: print(len(list(thursday_generator)))
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-28-b161cdcccc75> in <module>
      1 thursday_generator = get_days(date(2015, 1, 7), 3)
----> 2 print(len(list(thursday_generator)))

<ipython-input-16-0691db329606> in get_days(start, day_index, end)
      5     while end and start < end or not end:
      6         yield start
----> 7         start += week
      8

OverflowError: date value out of range