我想生成两个日期之间的日期列表(一周的第 N 天)。
例如,给定日期“20111101”和“20111201”,假设我想生成该月的第三个星期三的日期,我想生成日期:
["20111116", "20111221"]
所以我想写一个这样的函数:
def generateNthWeekdayDatesList(startdate, enddate, nthday=3, dayofweek="wed"):
pass
实现此功能的最佳(即最Pythonic)方法是什么?
最佳答案
这是使用generator的情况非常适合/pythonic。
def nth_day_of_month(start, end, nth, weekday):
assert start.day == 1, "start on the first day of a month"
assert nth > 0
assert 1 <= weekday <= 7
candidate = start
seen_in_month = 0
while candidate <= end:
if candidate.isoweekday() == weekday:
seen_in_month += 1
if seen_in_month == nth:
yield candidate
current_month = candidate.month
while candidate.month == current_month:
candidate += timedelta(1)
seen_in_month = 0
else:
if (candidate + timedelta(1)).month != candidate.month:
seen_in_month = 0
candidate += timedelta(1)
else:
if (candidate + timedelta(1)).month != candidate.month:
seen_in_month = 0
candidate += timedelta(1)
# third wednesday
print list(nth_day_of_month(date(2011, 1, 1), date(2012, 1, 1), nth=3, weekday=3))
# fifth sunday
print list(nth_day_of_month(date(2011, 1, 1), date(2012, 1, 1), nth=5, weekday=7))
# 9th monday
print list(nth_day_of_month(date(2011, 1, 1), date(2012, 1, 1), nth=9, weekday=1))
您甚至可以创建一个无限的生成器(永不停歇的生成器):
def infinite_nth_day_of_month(start, nth, weekday):
assert start.day == 1, "start on the first day of a month"
assert nth > 0
assert 1 <= weekday <= 7
candidate = start
seen_in_month = 0
while True:
if candidate.isoweekday() == weekday:
seen_in_month += 1
if seen_in_month == nth:
yield candidate
current_month = candidate.month
while candidate.month == current_month:
candidate += timedelta(1)
seen_in_month = 0
else:
if (candidate + timedelta(1)).month != candidate.month:
seen_in_month = 0
candidate += timedelta(1)
else:
if (candidate + timedelta(1)).month != candidate.month:
seen_in_month = 0
candidate += timedelta(1)
# this will create an infinite list, not a good idea
# print list(infinite_nth_day_of_month(date(2011, 1, 1), 3, 3))
import itertools
date_generator = infinite_nth_day_of_month(date(2011, 1, 1), 3, 3)
# create a list the 10000 third wednesdays of 2011 and into the future
date_list = list(itertools.islice(date_generator, 10000))
>>> print date_list[0]
2011-01-19
>>> print date_list[-1]
2844-04-20
请参阅 itertools 的文档.
如果提供给无限生成器的参数创建了一个永远不会产生任何东西的生成器(例如第 9 个星期二),那么它就不好了。在这种情况下,它将无休止地搜索,直到达到 datetime.date
支持的最大日期并引发 OverflowError:日期值超出范围
。
关于python - 从两个日期生成日期列表的最Pythonic方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8613565/