我正在尝试创建一个生成器函数来重复工作日(平日),跳过周末(假期也不错!)。到目前为止,我只简单地迭代函数数天:Python日期范围生成器在工作日内
def daterange(startDate, endDate):
for i in xrange(int((endDate - startDate).days)):
yield startDate + timedelta(i)
我挣扎找出一个清洁,高效和Python的方式使发电机跳过周末和节假日。提前致谢!
我正在尝试创建一个生成器函数来重复工作日(平日),跳过周末(假期也不错!)。到目前为止,我只简单地迭代函数数天:Python日期范围生成器在工作日内
def daterange(startDate, endDate):
for i in xrange(int((endDate - startDate).days)):
yield startDate + timedelta(i)
我挣扎找出一个清洁,高效和Python的方式使发电机跳过周末和节假日。提前致谢!
我会强烈建议使用dateutil库这样的任务。一个基本的(不忽略节假日)迭代器来工作日内然后简单地说就是:
from dateutil.rrule import DAILY, rrule, MO, TU, WE, TH, FR
def daterange(start_date, end_date):
return rrule(DAILY, dtstart=start_date, until=end_date, byweekday=(MO,TU,WE,TH,FR))
不错的例子! +1 – 2012-07-18 21:14:41
这实际上是做你说的吗?我在Linux和Mac OS上试用了Python 2.7和3.3,并且在所有情况下都会返回包括周末在内的所有日子。如果你看看'dateutil.rrule.WDAYMASK',你可能会发现它是一个0-6的列表,即所有的日子,而不仅仅是星期一到星期五。 – 2013-06-25 10:21:12
@JohnZwinck对,WDAYMASK确实不正确(至少在当前版本的dateutil中)。我更新了答案以反映这一点。 – earl 2013-06-25 22:06:44
假设startDate
和endDate
是日期时间或日期对象,您可以使用the weekday
method来获取星期几,然后在星期六或星期天跳过它。只要做:
def daterange(startDate, endDate):
for i in xrange(int((endDate - startDate).days)):
nextDate = startDate + timedelta(i)
if nextDate.weekday() not in (5, 6):
yield startDate + timedelta(i)
对于假期,你将不得不手动检查你想要的每个假期。有些假期是以复杂的方式定义的,所以这可能有点棘手。
有一个有用的库叫做dateutil
,可以为你做这种事情。它可以生成日期范围(或基于自定义规则的日期),排除特定日期,考虑从一天开始的一周等等。还有比内置日期时间库更灵活的timedelta。
文档在http://labix.org/python-dateutil/ - 和可用PyPI上
def get_date_range(start, end, workdays=None, holidays=None, skip_non_workdays=True):
"""
This function calculates the durations between 2 dates skipping non workdays and holidays as specified
:rtype : tuple
:param start: date
:param end: date
:param workdays: string [Comma Separated Values, 0 - Monday through to 6 - Sunday e.g "0,1,2,3,4"]
:param holidays: list
:param skip_non_workdays: boolean
:return:
"""
from datetime import timedelta
duration = 0
# define workdays
if workdays is None:
workdays = [0, 1, 2, 3, 4]
else:
workdays = workdays.split(",")
# check if we need to skip non workdays
if skip_non_workdays is False:
workdays = [0, 1, 2, 3, 4, 5, 6]
# validate dates
if end < start:
return False, "End date is before start date"
# now its time for us to iterate
i = start
while i <= end:
# first let's give benefit of the doubt
incr = True
# lets see if day is in the workday array if not then fault it's existence here
try:
workdays.index(i.weekday())
except ValueError:
incr = False
# lets check if day is an holiday, charge guilty if so.
# We are checking the index in holiday array
try:
holidays.index(i)
incr = False
except (ValueError, AttributeError):
pass
if incr:
duration += 1
print "This day passed the criterion %s" % i
i += timedelta(1)
return True, duration
看到这个问题的假期:http://stackoverflow.com/questions/1986207/holiday-calendars-file -formats-et-al – 2012-07-18 21:30:06