2012-07-18 26 views
8

İş günlerinde (hafta içi) yinelemek, hafta sonlarını atlamak için bir jeneratör işlevi oluşturmaya çalışıyorum (ve tatiller de güzel olurdu!). Ben jeneratör hafta sonları ve tatil günleri atlamak yapmak için bir temiz, verimli ve pythonic şekilde anlamaya mücadele ediyorumPython tarih aralığı jeneratörü iş günlerinde

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

: Şu ana kadar sadece gün içinde bir işlevi basitçe yineler var. Şimdiden teşekkürler!

+1

tatil için bu soruya bakın: http://stackoverflow.com/questions/1986207/holiday-calendars-file -formats-et-al –

cevap

23

ve mevcut Güçlü tür görevler için dateutil kitaplığı kullanarak tavsiye ederim. iş günü boyunca temel (değil görmezden tatil günleri) yineleyici sonra basitçe:

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

Güzel örnek! +1 –

+0

Bu gerçekten söylediklerini yapıyor mu? Linux ve Mac OS üzerinde Python 2.7 ve 3.3 üzerinde çalıştı ve her durumda, hafta sonları da dahil olmak üzere tüm günlerde döner. Eğer "dateutil.rrule.WDAYMASK" 'a bakarsanız, bunun 0-6, yani tüm günlerde, sadece pazartesi-cuma günleri olmadığını görebilirsiniz. –

+0

@JohnZwinck Sağ, WDAYMASK doğru değil (en azından dateutil'in geçerli sürümleriyle). Yanıtı bunu yansıtacak şekilde güncelledim. – earl

6

startDate ve endDate'un varsayımları tarih veya tarih nesneleridir, haftanın gününü almak için the weekday method'u kullanabilir, ardından cumartesi veya Pazar günü ise atlayabilirsiniz. Sadece yapın: tatil için

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) 

istediğiniz her tatil için elle kontrol etmek zorunda kalacak. Bazı tatiller karmaşık şekillerde tanımlanmıştır, bu yüzden bu biraz zor olabilir.

7

dateutil adlı yararlı bir kitaplık var, sizin için bu tür bir şey yapabilir. Belirli günler hariç, tarihler (veya özel kurallara dayanan tarihler) oluşturabilir, bir güne başlayarak bir güne başlayabilir, vs… Ayrıca, yerleşik datetime kitaplığından biraz daha esnek bir zaman çizelgesi vardır. http://labix.org/python-dateutil/ de

Dokümanlar - 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 
İlgili konular