Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید


Recipe 3.5. Calculating the Number of Weekdays Between Two Dates


Credit: Anna Martelli Ravenscroft


Problem


You want to calculate the number of
weekdays (working days), as opposed to calendar days, that fall
between two dates.


Solution


Since weekends and other "days off"
vary by country, by region, even sometimes within a single company,
there is no built-in way to perform this task. However, using
dateutil along with datetime
objects, it's reasonably simple to code a solution:

from dateutil import rrule 
import datetime
def workdays(start, end, holidays=0, days_off=None):
if days_off is None:
days_off = 5, 6 # default to: saturdays and sundays
workdays = [x for x in range(7) if x not in days_off]
days = rrule.rrule(rrule.DAILY, dtstart=start, until=end,
byweekday=workdays)
return days.count( ) - holidays
if _ _name_ _ == '_ _main_ _':
# test when run as main script
testdates = [ (datetime.date(2004, 9, 1),
datetime.date(2004, 11, 14), 2),
(datetime.date(2003, 2, 28), datetime.date(2003, 3, 3), 1), ]
def test(testdates, days_off=None):
for s, e, h in testdates:
print 'total workdays from %s to %s is %s with %s holidays' % (
s, e, workdays(s, e, h, days_off), h)
test(testdates)
test(testdates, days_off=[6])


Discussion


This project was my very first one in Python: I needed to know the
number of actual days in training of our trainees, given a start date
and end date (inclusive). This problem was a bit trickier back in
Python 2.2; today, the datetime module and the
dateutil third-party package make the problem much
simpler to solve.

Function workdays starts by assigning a reasonable
default value to variable days_off (unless an
explicit value was passed for it as an argument), which is a sequence
of the weekday numbers of our normal days off. In my company, weekly
days off varied among individuals but were usually fewer than the
workdays, so it was easier to track and modify the days off rather
than the workdays. I made this an argument to the function so that I
can easily pass a different value for days_off if
and when I have different needs. Then, the function uses a list
comprehension to create a list of actual weekly workdays, which are
all weekdays not in days_off. Now the function is
ready to do its calculations.

The workhorse in this recipe is an instance, named
days, of dateutil's
rrule (recurrence rule) class. Class
rrule may be instantiated with various parameters
to produce a rule object. In this example, I pass a frequency
(rrule.DAILY), a beginning date and an ending
dateboth of which must be datetime.date
objectsand which weekdays to include
(workdays). Then, I simply call method
days.count to count the number of occurrences
generated by the rule. (See Recipe 3.3 for other uses for the
count method of rrule.)

You can easily set your own definition of
weekend: just pass as days_off
whichever values you need. In this recipe, the default value is set
to the standard U.S. weekend of Saturday and Sunday. However, if your
company normally works a four-day week, say, Tuesday through Friday,
you would pass days_off=(5, 6, 0). Just be sure to
pass the days_off value as an iterable, such as a
list or tuple, even if, as in
the second test, you only have a single day in that container.

A simple but useful enhancement might be to automatically check
whether your start and end dates are weekends (for weekend-shift
workers), and use an if/else to handle the weekend
shifts, with appropriate changes to days_off.
Further enhancements would be to add the ability to enter sick days,
or to perform a call to an automatic holiday lookup function, rather
than passing the number of holidays directly, as I do in this recipe.
See Recipe 3.6 for a
simple implementation of a holidays list for this purpose.


See Also


Refer to the dateutil documentation, which is
available at ,
datetime documentation in the Library
Reference
; Recipe 3.3 for another use of
rrule.count; Recipe 3.6 for automatic holiday
lookup.

/ 394