1.1 --- a/imiptools/data.py Fri Oct 20 22:40:55 2017 +0200
1.2 +++ b/imiptools/data.py Fri Oct 20 23:11:15 2017 +0200
1.3 @@ -1214,11 +1214,11 @@
1.4
1.5 return delegators
1.6
1.7 -def make_rule_period(start, duration, tzid, attr):
1.8 +def make_rule_period(start, duration, attr, tzid):
1.9
1.10 """
1.11 Make a period for the rule period starting at 'start' with the given
1.12 - 'duration' employing the given 'tzid' and datetime 'attr'.
1.13 + 'duration' employing the given datetime 'attr' and 'tzid'.
1.14 """
1.15
1.16 # Determine the resolution of the period.
1.17 @@ -1232,6 +1232,44 @@
1.18
1.19 return RecurringPeriod(start, end, tzid, "RRULE", attr)
1.20
1.21 +def get_rule_periods(rrule, start, duration, attr, tzid, end, inclusive=False):
1.22 +
1.23 + """
1.24 + Return periods for the given 'rrule', employing the 'start', 'duration',
1.25 + datetime 'attr' and 'tzid'.
1.26 +
1.27 + The specified 'end' datetime indicates the end of the window for which
1.28 + periods shall be computed.
1.29 +
1.30 + If 'inclusive' is set to a true value, any period occurring at the 'end'
1.31 + will be included.
1.32 + """
1.33 +
1.34 + parameters = rrule and get_parameters(rrule)
1.35 + selector = get_rule(start, rrule)
1.36 +
1.37 + until = parameters.get("UNTIL")
1.38 +
1.39 + if until:
1.40 + until_dt = to_timezone(get_datetime(until, attr), tzid)
1.41 + end = end and min(until_dt, end) or until_dt
1.42 + inclusive = True
1.43 +
1.44 + # Obtain period instances, starting from the main period. Since counting
1.45 + # must start from the first period, filtering from a start date must be
1.46 + # done after the instances have been obtained.
1.47 +
1.48 + periods = []
1.49 +
1.50 + for recurrence_start in selector.materialise(start, end,
1.51 + parameters.get("COUNT"),
1.52 + parameters.get("BYSETPOS"),
1.53 + inclusive):
1.54 +
1.55 + periods.append(make_rule_period(recurrence_start, duration, attr, tzid))
1.56 +
1.57 + return periods
1.58 +
1.59 def get_periods(obj, start=None, end=None, inclusive=False):
1.60
1.61 """
1.62 @@ -1261,35 +1299,21 @@
1.63 if not rrule:
1.64 periods = [main_period]
1.65
1.66 + # Recurrence rules create multiple instances to be checked.
1.67 + # Conflicts may only be assessed within a period defined by policy
1.68 + # for the agent, with instances outside that period being considered
1.69 + # unchecked.
1.70 +
1.71 elif end or parameters and parameters.has_key("UNTIL") or parameters.has_key("COUNT"):
1.72
1.73 - # Recurrence rules create multiple instances to be checked.
1.74 - # Conflicts may only be assessed within a period defined by policy
1.75 - # for the agent, with instances outside that period being considered
1.76 - # unchecked.
1.77 + # Define a selection period with a start point. The end will be handled
1.78 + # in the materialisation process.
1.79
1.80 - selector = get_rule(dtstart, rrule)
1.81 + selection_period = Period(start, None)
1.82 periods = []
1.83
1.84 - until = parameters.get("UNTIL")
1.85 - if until:
1.86 - until_dt = to_timezone(get_datetime(until, dtstart_attr), tzid)
1.87 - end = end and min(until_dt, end) or until_dt
1.88 - inclusive = True
1.89 -
1.90 - # Define a selection period with a start point. The end will be handled
1.91 - # in the materialisation process below.
1.92 -
1.93 - selection_period = Period(start, None)
1.94 -
1.95 - # Obtain period instances, starting from the main period. Since counting
1.96 - # must start from the first period, filtering from a start date must be
1.97 - # done after the instances have been obtained.
1.98 -
1.99 - for recurrence_start in selector.materialise(dtstart, end,
1.100 - parameters.get("COUNT"), parameters.get("BYSETPOS"), inclusive):
1.101 -
1.102 - period = make_rule_period(recurrence_start, main_period.get_duration(), tzid, dtstart_attr)
1.103 + for period in get_rule_periods(rrule, dtstart,
1.104 + main_period.get_duration(), dtstart_attr, tzid, end, inclusive):
1.105
1.106 # Use the main period where it occurs.
1.107