My favorites | Sign in
Project Home Issues
New issue   Search
for
  Advanced search   Search tips   Subscriptions

Issue 116 attachment: recurring.py (3.5 KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def fetchRecurring(start, end, events):
''' returns list of recurring entries that have instances in the specified time range (between start and end) '''


def recursDuring(entry):
''' returns whether the recurring entry has an instance during the date range from start to end '''
# ignore if the first instance of the event is after our range
origin = entry.start
recurring = []

# TODO: should use date class instead of datetime class

if origin > end:
# ignore event - all instances occur in future
return recurring

def recurWeek(incr):
''' calculate either weekly or biweekly repeats. 'incr' will be either 7 or 14 '''
leadup = start - origin
rm = leadup.seconds

# account for partial days since start/end ranges usually have midnight as a time
days = leadup.days + 1 if rm > 0 else leadup.days

if origin > start:
# first instance is within the current range
begin = origin
else:
# set the first date we check BEFORE the specified range, so we don't jump over any relevant instances
diff = days % incr
begin = start - timedelta(days=diff)

# start comparisons
candidate = begin.replace(hour=origin.hour, minute=origin.minute, second=origin.second)
duration = entry.end - entry.start

while candidate < end:
if candidate > start:
instance = candidate
recurring.append(construct(entry, instance, instance + duration))

# increment by event frequency (e.g. 7 days for weekly)
candidate = candidate + timedelta(days=incr)


if entry.frequency == "D":
# get the first date of relevance
if origin > start:
candidate = begin = origin
else:
begin = start
candidate = begin.replace(hour=origin.hour, minute=origin.minute, second=origin.second)

duration = entry.end - entry.start

while candidate < end:
if candidate > start:
instance = candidate
recurring.append(construct(entry, instance, instance + duration))

# get the next day
candidate = candidate + timedelta(days=1)

elif entry.frequency == "W":
recurWeek(7)

elif entry.frequency == "B":
recurWeek(14)

elif entry.frequency == "M":
candidate = begin = origin

duration = entry.end - entry.start

while candidate < end:
# checking month

if candidate > start:
instance = candidate
recurring.append(construct(entry, instance, instance + duration))

# increment by event frequency
nextmonth = candidate.month + 1
nextmonth = 1 if nextmonth > 12 else nextmonth
candidate = candidate.replace(month=nextmonth)

return recurring


# call the recursDuring method on each member in the list of event objects (from database)
output = map(recursDuring, events)

# map function returns a nested list (array) so we flatten it
return [item for sublist in output for item in sublist] if output else []
Powered by Google Project Hosting