| commit 16: | 98aeaddf15d6 |
| parent 15: | 7d7ea72e8971 |
| branch: | timerecurrence |
Improve rrule module:
* Sprinkle some edoc and comments
* Explicitely define which function to export
* Clean up unused functions
* Fix warning messages during compilation
* Remove unused parameter ListRanges in satisfy/3
* Add a new function in_range/2 which check if a range match
all the constraints defined by some given rules
9 months ago
Changed (Δ8 bytes):
raw changeset »
src/rrule.erl (45 lines added, 39 lines removed)
Up to file-list src/rrule.erl:
1 |
%% @doc Datetime conversion functions to convert to and from datetime tuples |
|
2 |
%% for standard formats. |
|
1 |
%% @doc rrule provides a set of function to related to time recurrence. |
|
2 |
%% |
|
3 |
3 |
%% |
4 |
%% @type datetime() = {date(), time()} |
|
5 |
%% @type date() = {Year::integer(), Month::integer(), Day::integer()} |
|
6 |
%% @type time() = {Hour::integer(), Min::integer(), Sec::integer()} |
|
7 |
%% @type daterange() = {date(), date()} |
|
4 |
%% @type constraint() = {atom(), term()} |
|
5 |
%% @type rule() = tuple(list(constraint()), DurationInHour::integer()) |
|
6 |
%% @type rules() = list(rule()) |
|
8 |
7 |
%% |
9 |
8 |
%% @author Bruno Mahe |
10 |
9 |
-module(rrule). |
11 |
10 |
|
12 |
11 |
|
13 |
- |
|
12 |
-export([in_range/2]). |
|
13 |
-export([satisfy/3]). |
|
14 |
14 |
|
15 |
15 |
|
16 |
%% @doc Convert day of the week into an integer usable by the calendar module |
|
17 |
%% @see calendar:day_of_the_week/1 |
|
18 |
%% @see calendar:day_of_the_week/3 |
|
19 |
%% @spec day_of_the_week(atom()) -> integer() |
|
16 |
20 |
day_of_the_week(monday) -> 1; |
17 |
21 |
day_of_the_week(tuesday) -> 2; |
18 |
22 |
day_of_the_week(wednesday) -> 3; |
| … | … | @@ -22,6 +26,8 @@ day_of_the_week(saturday) -> 6; |
22 |
26 |
day_of_the_week(sunday) -> 7. |
23 |
27 |
|
24 |
28 |
|
29 |
%% @doc Convert month name into an integer |
|
30 |
%% @spec month(atom()) -> integer() |
|
25 |
31 |
month(january) -> 1; |
26 |
32 |
month(february) -> 2; |
27 |
33 |
month(march) -> 3; |
| … | … | @@ -37,14 +43,6 @@ month(december) -> 11. |
37 |
43 |
|
38 |
44 |
|
39 |
45 |
|
40 |
new() -> []. |
|
41 |
||
42 |
% Constraints Duration |
|
43 |
%Rule => {[{month, june}, {weekday, monday}, {hour, 8}], 8}) |
|
44 |
%Rules => [Rule] |
|
45 |
||
46 |
||
47 |
add_rule(Rules, Rule) -> [Rule|Rules]. |
|
48 |
46 |
|
49 |
47 |
|
50 |
48 |
find_month_in_range(Month, BeginningRangeDateTime, EndRangeDateTime) -> |
| … | … | @@ -139,10 +137,9 @@ find_day_in_range(Day, BeginningRangeDat |
139 |
137 |
find_day_in_range(Day, BeginningRangeDateTime, EndRangeDateTime, ListDays) -> |
140 |
138 |
|
141 |
139 |
{BeginningRangeDate, BeginningRangeTime} = BeginningRangeDateTime, |
142 |
{BeginRangeYear, BeginRangeMonth, BeginRangeDay} = BeginningRangeDate, |
|
143 |
140 |
|
144 |
{EndRangeDate, EndRangeTime} = EndRangeDateTime, |
|
145 |
{EndRangeYear, EndRangeMonth, EndRangeDay} = EndRangeDate, |
|
141 |
{EndRangeDate, _} = EndRangeDateTime, |
|
142 |
{_, _, EndRangeDay} = EndRangeDate, |
|
146 |
143 |
|
147 |
144 |
FoundListDays = case EndRangeDay of |
148 |
145 |
Day -> BeginSubRange = case EndRangeDate of |
| … | … | @@ -165,18 +162,19 @@ find_day_in_range(Day, BeginningRangeDat |
165 |
162 |
end. |
166 |
163 |
|
167 |
164 |
|
165 |
%% @doc Returns a list or ranges which satisfy a list of constraints |
|
166 |
%% @spec satisfy(rule(), datetime(), datetime()) -> list({datetime(), datetime()) |
|
167 |
satisfy({[], _}, When, Until) -> {When, Until}; |
|
168 |
168 |
|
169 |
satisfy({[], _}, _, _, ListRanges) -> ListRanges; |
|
170 |
||
171 |
satisfy({[{month, Month}| Constraints], Duration}, BeginRange, EndRange |
|
169 |
satisfy({[{month, Month}| Constraints], Duration}, BeginRange, EndRange) when is_atom(Month) -> |
|
172 |
170 |
ConstraintMonth = month(Month), |
173 |
171 |
|
174 |
satisfy({[{month, ConstraintMonth}|Constraints], Duration}, BeginRange, EndRange |
|
172 |
satisfy({[{month, ConstraintMonth}|Constraints], Duration}, BeginRange, EndRange); |
|
175 |
173 |
|
176 |
satisfy({[{month, Month}|Constraints], Duration}, BeginRange, EndRange |
|
174 |
satisfy({[{month, Month}|Constraints], Duration}, BeginRange, EndRange) when is_integer(Month), Month > 0, Month < 13 -> |
|
177 |
175 |
|
178 |
176 |
CheckRanges = fun({BeginSubRange, EndSubRange}) -> |
179 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange |
|
177 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange) |
|
180 |
178 |
end, |
181 |
179 |
|
182 |
180 |
lists:map( |
| … | … | @@ -184,10 +182,10 @@ satisfy({[{month, Month}|Constraints], D |
184 |
182 |
find_month_in_range(Month, BeginRange, EndRange) |
185 |
183 |
); |
186 |
184 |
|
187 |
satisfy({[{day, Day}|Constraints], Duration}, BeginRange, EndRange |
|
185 |
satisfy({[{day, Day}|Constraints], Duration}, BeginRange, EndRange) when is_integer(Day), Day > 0, Day < 32 -> |
|
188 |
186 |
|
189 |
187 |
CheckRanges = fun({BeginSubRange, EndSubRange}) -> |
190 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange |
|
188 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange) |
|
191 |
189 |
end, |
192 |
190 |
|
193 |
191 |
lists:map( |
| … | … | @@ -195,7 +193,7 @@ satisfy({[{day, Day}|Constraints], Durat |
195 |
193 |
find_day_in_range(Day, BeginRange, EndRange) |
196 |
194 |
); |
197 |
195 |
|
198 |
satisfy({[{weekday, WeekDay}|Constraints], Duration}, BeginRange, EndRange |
|
196 |
satisfy({[{weekday, WeekDay}|Constraints], Duration}, BeginRange, EndRange) when is_atom(WeekDay) -> |
|
199 |
197 |
|
200 |
198 |
{BeginRangeDate, BeginRangeTime} = BeginRange, |
201 |
199 |
|
| … | … | @@ -218,7 +216,7 @@ satisfy({[{weekday, WeekDay}|Constraints |
218 |
216 |
), |
219 |
217 |
|
220 |
218 |
CheckRanges = fun({BeginSubRange, EndSubRange}) -> |
221 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange |
|
219 |
satisfy({Constraints, Duration}, BeginSubRange, EndSubRange) |
|
222 |
220 |
end, |
223 |
221 |
|
224 |
222 |
lists:map( |
| … | … | @@ -228,9 +226,9 @@ satisfy({[{weekday, WeekDay}|Constraints |
228 |
226 |
|
229 |
227 |
|
230 |
228 |
|
231 |
satisfy({[{time, Hour}|Constraints], Duration}, BeginRange, EndRange, ListRanges) when is_integer(Hour), Hour > 0, Hour < 25 -> |
|
232 |
satisfy({[{hour, {Hour, 0}}|Constraints], Duration}, BeginRange, EndRange, ListRanges); |
|
233 |
satisfy({[{time, |
|
229 |
satisfy({[{time, Hour}|Constraints], Duration}, BeginRange, EndRange) when is_integer(Hour), Hour > 0, Hour < 25 -> |
|
230 |
satisfy({[{time, {Hour, 0}}|Constraints], Duration}, BeginRange, EndRange); |
|
231 |
satisfy({[{time, {Hour, Minutes}}|Constraints], Duration}, BeginRange, EndRange) when is_integer(Hour), Hour > 0, Hour < 25 -> |
|
234 |
232 |
|
235 |
233 |
{BeginRangeDate, BeginRangeTime} = BeginRange, |
236 |
234 |
{BeginRangeHour, BeginRangeMinute, BeginRangeSeconds} = BeginRangeTime, |
| … | … | @@ -261,8 +259,6 @@ satisfy({[{time, {Hour, Minutes}}|Constr |
261 |
259 |
|
262 |
260 |
|
263 |
261 |
DatePlusDuration = datetime:time_diff({Date, {Hour, Minutes, 0}}, Duration*3600), |
264 |
{DDDate, DDTime} = DatePlusDuration, |
|
265 |
{DDHour, DDMinute, DDSeconds} = DDTime, |
|
266 |
262 |
|
267 |
263 |
DatePlusDurationInSec = calendar:datetime_to_gregorian_seconds(DatePlusDuration), |
268 |
264 |
EndRangeInSec = calendar:datetime_to_gregorian_seconds(EndRange), |
| … | … | @@ -284,7 +280,7 @@ satisfy({[{time, {Hour, Minutes}}|Constr |
284 |
280 |
CheckRanges = fun({BeginSubRange, EndSubRange}) -> |
285 |
281 |
case {BeginSubRange, EndSubRange} of |
286 |
282 |
{none, none} -> []; |
287 |
_ -> satisfy({Constraints, Duration}, BeginSubRange, EndSubRange |
|
283 |
_ -> satisfy({Constraints, Duration}, BeginSubRange, EndSubRange) |
|
288 |
284 |
end |
289 |
285 |
end, |
290 |
286 |
|
| … | … | @@ -298,15 +294,25 @@ satisfy({[{time, {Hour, Minutes}}|Constr |
298 |
294 |
|
299 |
295 |
|
300 |
296 |
|
301 |
%in_range({Constraints, Duration} = Rule, {Date, Time}) -> |
|
302 |
||
303 |
% |
|
297 |
%% @doc Check if a range match the constraints defined by some rules |
|
298 |
%% @spec in_range(rules(), {datetime(), datetime()}) -> bool() |
|
299 |
in_range(Rules, {When, Until}) when is_list(Rules) -> lists:any(fun(Rule) -> in_range(Rule, {When, Until})end, Rules); |
|
304 |
300 |
|
305 |
in_range(Rule |
|
301 |
in_range(Rule, {When, Until}) when is_tuple(Rule) -> |
|
306 |
302 |
|
307 |
303 |
|
304 |
Candidates = lists:flatten( |
|
305 |
satisfy(Rule, When, Until) |
|
306 |
), |
|
307 |
||
308 |
||
309 |
lists:any( |
|
310 |
fun({Begin, End}) -> |
|
311 |
datetime:range_in_range({When, Until}, {Begin, End}) |
|
312 |
end, |
|
313 |
Candidates |
|
308 |
314 |
|
315 |
). |
|
309 |
316 |
|
310 |
317 |
|
311 |
318 |
|
312 |
%in_range(Rules, {When, Until}) -> true | false. |
