2012-07-18 24 views
8

週末をスキップするジェネレータ関数を作成しようとしています(そして休日も素晴らしいかもしれません)。これまでのところ、私は唯一日間の単純反復する機能を持っている:Pythonの日付範囲ジェネレータ(営業日)

def daterange(startDate, endDate): 
    for i in xrange(int((endDate - startDate).days)): 
     yield startDate + timedelta(i) 

私は発電機が土日祝日をスキップさせるために、クリーンで効率的かつ神託の方法を把握するのに苦労しています。前もって感謝します!

+1

休日のため、この質問を参照してください。http://stackoverflow.com/questions/1986207/holiday-calendars-fileを-formats-et-al –

答えて

23

で、利用可能な私は強いようなタスクのための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)) 
+0

いい例! +1 –

+0

これは実際にあなたが言うことをしていますか?私はLinuxとMac OS上のPython 2.7と3.3でそれを試してみましたが、すべての場合、週末を含め、すべての日が返されます。 'dateutil.rrule.WDAYMASK'を見ると、それは月曜日から金曜日だけでなく、すべての日の0から6までのリストであることがわかります。 –

+0

@JohnZwinckそうですね、WDAYMASKは実際には間違いです(少なくとも現在のバージョンのdateutilでは)。私はこれを反映するために答えを更新しました。 – earl

6

startDateendDateが日時オブジェクトまたは日付オブジェクトであると仮定すると、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) 

あなたが望む休日ごとに手動でチェックする必要があります。いくつかの休日は複雑な方法で定義されているので、これはややこしいかもしれません。

7

dateutilと呼ばれる便利なライブラリがあります。このようなことができます。特定の日を除いて、日付の範囲(またはカスタムルールに基づく日付)を生成することができます。また、1日を開始する週を考慮します...また、組み込みのdatetimeライブラリよりもやや柔軟なtimedeltaを持っています。

http://labix.org/python-dateutil/のドキュメント - は、PyPI

0
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