| 1 | # Copyright (c) 2006-2006 LOGILAB S.A. (Paris, FRANCE). |
|---|
| 2 | # http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|---|
| 3 | # |
|---|
| 4 | # This program is free software; you can redistribute it and/or modify it under |
|---|
| 5 | # the terms of the GNU General Public License as published by the Free Software |
|---|
| 6 | # Foundation; either version 2 of the License, or (at your option) any later |
|---|
| 7 | # version. |
|---|
| 8 | # |
|---|
| 9 | # This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|---|
| 11 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|---|
| 12 | # |
|---|
| 13 | # You should have received a copy of the GNU General Public License along with |
|---|
| 14 | # this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 15 | # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 16 | |
|---|
| 17 | """date manipulation helper functions""" |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | try: |
|---|
| 21 | from mx.DateTime import RelativeDateTime, strptime |
|---|
| 22 | STEP = 1 |
|---|
| 23 | except ImportError: |
|---|
| 24 | from warnings import warn |
|---|
| 25 | warn("mxDateTime not found, holiday management won't be available") |
|---|
| 26 | from datetime import timedelta |
|---|
| 27 | STEP = timedelta(days=1) |
|---|
| 28 | else: |
|---|
| 29 | endOfMonth = RelativeDateTime(months=1, day=-1) |
|---|
| 30 | |
|---|
| 31 | FRENCH_FIXED_HOLIDAYS = { |
|---|
| 32 | 'jour_an' : '%s-01-01', |
|---|
| 33 | 'fete_travail' : '%s-05-01', |
|---|
| 34 | 'armistice1945' : '%s-05-08', |
|---|
| 35 | 'fete_nat' : '%s-07-14', |
|---|
| 36 | 'assomption' : '%s-08-15', |
|---|
| 37 | 'toussaint' : '%s-11-01', |
|---|
| 38 | 'armistice1918' : '%s-11-11', |
|---|
| 39 | 'noel' : '%s-12-25', |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | FRENCH_MOBILE_HOLIDAYS = { |
|---|
| 44 | 'paques2004' : '2004-04-12', |
|---|
| 45 | 'ascension2004' : '2004-05-20', |
|---|
| 46 | 'pentecote2004' : '2004-05-31', |
|---|
| 47 | |
|---|
| 48 | 'paques2005' : '2005-03-28', |
|---|
| 49 | 'ascension2005' : '2005-05-05', |
|---|
| 50 | 'pentecote2005' : '2005-05-16', |
|---|
| 51 | |
|---|
| 52 | 'paques2006' : '2006-04-17', |
|---|
| 53 | 'ascension2006' : '2006-05-25', |
|---|
| 54 | 'pentecote2006' : '2006-06-05', |
|---|
| 55 | |
|---|
| 56 | 'paques2007' : '2007-04-09', |
|---|
| 57 | 'ascension2007' : '2007-05-17', |
|---|
| 58 | 'pentecote2007' : '2007-05-28', |
|---|
| 59 | |
|---|
| 60 | 'paques2008' : '2008-03-24', |
|---|
| 61 | 'ascension2008' : '2008-05-01', |
|---|
| 62 | 'pentecote2008' : '2008-05-12', |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | def get_national_holidays(begin, end): |
|---|
| 66 | """return french national days off between begin and end""" |
|---|
| 67 | holidays = [strptime(datestr, '%Y-%m-%d') |
|---|
| 68 | for datestr in FRENCH_MOBILE_HOLIDAYS.values()] |
|---|
| 69 | for year in xrange(begin.year, end.year+1): |
|---|
| 70 | holidays += [strptime(datestr % year, '%Y-%m-%d') |
|---|
| 71 | for datestr in FRENCH_FIXED_HOLIDAYS.values()] |
|---|
| 72 | return [day for day in holidays if begin <= day < end] |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | def add_days_worked(start, days): |
|---|
| 76 | """adds date but try to only take days worked into account""" |
|---|
| 77 | weeks, plus = divmod(days, 5) |
|---|
| 78 | end = start+(weeks * 7) + plus |
|---|
| 79 | if end.day_of_week > 4: |
|---|
| 80 | end += 2 |
|---|
| 81 | end += len([x for x in get_national_holidays(start, end+1) |
|---|
| 82 | if x.day_of_week < 5]) |
|---|
| 83 | return end |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | def date_range(begin, end, step=STEP): |
|---|
| 87 | """ |
|---|
| 88 | enumerate dates between begin and end dates. |
|---|
| 89 | |
|---|
| 90 | step can either be oneDay, oneHour, oneMinute, oneSecond, oneWeek |
|---|
| 91 | use endOfMonth to enumerate months |
|---|
| 92 | """ |
|---|
| 93 | date = begin |
|---|
| 94 | while date < end : |
|---|
| 95 | yield date |
|---|
| 96 | date += step |
|---|