Package logilab-common-0 ::
Package 39 ::
Package 0 ::
Module date
|
|
1 """Date manipulation helper functions.
2
3 :copyright: 2006-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
4 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
5 :license: General Public License version 2 - http://www.gnu.org/licenses
6 """
7 __docformat__ = "restructuredtext en"
8
9 import math
10
11 try:
12 from mx.DateTime import RelativeDateTime, strptime, Date
13 STEP = 1
14 except ImportError:
15 from warnings import warn
16 warn("mxDateTime not found, holiday management won't be available")
17 from datetime import timedelta
18 STEP = timedelta(days=1)
19 else:
20 endOfMonth = RelativeDateTime(months=1, day=-1)
21
22 FRENCH_FIXED_HOLIDAYS = {
23 'jour_an' : '%s-01-01',
24 'fete_travail' : '%s-05-01',
25 'armistice1945' : '%s-05-08',
26 'fete_nat' : '%s-07-14',
27 'assomption' : '%s-08-15',
28 'toussaint' : '%s-11-01',
29 'armistice1918' : '%s-11-11',
30 'noel' : '%s-12-25',
31 }
32
33
34 FRENCH_MOBILE_HOLIDAYS = {
35 'paques2004' : '2004-04-12',
36 'ascension2004' : '2004-05-20',
37 'pentecote2004' : '2004-05-31',
38
39 'paques2005' : '2005-03-28',
40 'ascension2005' : '2005-05-05',
41 'pentecote2005' : '2005-05-16',
42
43 'paques2006' : '2006-04-17',
44 'ascension2006' : '2006-05-25',
45 'pentecote2006' : '2006-06-05',
46
47 'paques2007' : '2007-04-09',
48 'ascension2007' : '2007-05-17',
49 'pentecote2007' : '2007-05-28',
50
51 'paques2008' : '2008-03-24',
52 'ascension2008' : '2008-05-01',
53 'pentecote2008' : '2008-05-12',
54 }
55
57 """return french national days off between begin and end"""
58 begin = Date(begin.year, begin.month, begin.day)
59 end = Date(end.year, end.month, end.day)
60 holidays = [strptime(datestr, '%Y-%m-%d')
61 for datestr in FRENCH_MOBILE_HOLIDAYS.values()]
62 for year in xrange(begin.year, end.year+1):
63 for datestr in FRENCH_FIXED_HOLIDAYS.values():
64 date = strptime(datestr % year, '%Y-%m-%d')
65 if date not in holidays:
66 holidays.append(date)
67 return [day for day in holidays if begin <= day < end]
68
69
71 """adds date but try to only take days worked into account"""
72 weeks, plus = divmod(days, 5)
73 end = start+(weeks * 7) + plus
74 if end.day_of_week >= 5:
75 end += 2
76 end += len([x for x in get_national_holidays(start, end+1)
77 if x.day_of_week < 5])
78 if end.day_of_week >= 5:
79 end += 2
80 return end
81
83 assert start <= end
84 days = int(math.ceil((end - start).days))
85 weeks, plus = divmod(days, 7)
86 if start.day_of_week > end.day_of_week:
87 plus -= 2
88 elif end.day_of_week == 6:
89 plus -= 1
90 open_days = weeks * 5 + plus
91 nb_week_holidays = len([x for x in get_national_holidays(start, end+1)
92 if x.day_of_week < 5 and x < end])
93 return open_days - nb_week_holidays
94
95
97 """
98 enumerate dates between begin and end dates.
99
100 step can either be oneDay, oneHour, oneMinute, oneSecond, oneWeek
101 use endOfMonth to enumerate months
102 """
103 date = begin
104 while date < end :
105 yield date
106 date += step
107