我正在嘗試創建一個生成器函數來重複工作日(平日),跳過週末(假期也不錯!)。到目前爲止,我只簡單地迭代函數數天: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