[california/wip/725785-create-recurring] Tighten up rrule-adding code in details parser
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/725785-create-recurring] Tighten up rrule-adding code in details parser
- Date: Fri, 20 Jun 2014 23:35:57 +0000 (UTC)
commit c2904479961b61f2d689dece2334e930a3c723fa
Author: Jim Nelson <jim yorba org>
Date: Fri Jun 20 15:57:44 2014 -0700
Tighten up rrule-adding code in details parser
src/component/component-details-parser.vala | 145 +++++++++++++++------------
src/tests/tests-quick-add-recurring.vala | 23 ++++-
2 files changed, 101 insertions(+), 67 deletions(-)
---
diff --git a/src/component/component-details-parser.vala b/src/component/component-details-parser.vala
index ecebe74..e5ee3cc 100644
--- a/src/component/component-details-parser.vala
+++ b/src/component/component-details-parser.vala
@@ -495,33 +495,22 @@ public class DetailsParser : BaseObject {
if (rrule != null || specifier == null)
return false;
- if (specifier.casefolded == DAILY) {
- set_rrule_daily(1);
-
- return true;
- }
+ if (specifier.casefolded == DAILY)
+ return set_rrule_daily(1);
if (specifier.casefolded == WEEKLY) {
// set the start date to today unless already known
if (start_date == null)
start_date = Calendar.System.today;
- set_rrule_weekly(iterate<Calendar.DayOfWeek>(start_date.day_of_week).to_array(), 1);
-
- return true;
+ return set_rrule_weekly(iterate<Calendar.DayOfWeek>(start_date.day_of_week).to_array(), 1);
}
- if (specifier.casefolded in UNIT_WEEKDAYS) {
- set_rrule_weekly(Calendar.DayOfWeek.weekdays, 1);
-
- return true;
- }
+ if (specifier.casefolded in UNIT_WEEKDAYS)
+ return set_rrule_weekly(Calendar.DayOfWeek.weekdays, 1);
- if (specifier.casefolded in UNIT_WEEKENDS) {
- set_rrule_weekly(Calendar.DayOfWeek.weekend_days, 1);
-
- return true;
- }
+ if (specifier.casefolded in UNIT_WEEKENDS)
+ return set_rrule_weekly(Calendar.DayOfWeek.weekend_days, 1);
return false;
}
@@ -537,11 +526,14 @@ public class DetailsParser : BaseObject {
// look for an amount modifying the specifier (creating an interval, i.e. "every 2 days"
// or "every 2nd day", hence parsing for ordinal)
+ bool is_ordinal = false;
int interval = parse_ordinal(unit);
if (interval >= 1) {
unit = stack.pop();
if (unit == null)
return false;
+
+ is_ordinal = true;
} else {
interval = 1;
}
@@ -549,33 +541,27 @@ public class DetailsParser : BaseObject {
// a day of the week
Calendar.DayOfWeek? dow = Calendar.DayOfWeek.parse(unit.casefolded);
if (dow != null) {
- set_rrule_weekly(iterate<Calendar.DayOfWeek>(
- Calendar.System.today.upcoming(dow, true).day_of_week).to_array_list().to_array(),
- interval);
+ Calendar.DayOfWeek[] by_days = iterate<Calendar.DayOfWeek>(
+ Calendar.System.today.upcoming(dow, true).day_of_week).to_array();
- return true;
+ // if interval is an ordinal, the rule is for "nth day of the month", so it's a week number
+ if (!is_ordinal)
+ return set_rrule_weekly(by_days, interval);
+ else
+ return set_rrule_nth_day_of_week(by_days, interval);
}
// "day"
- if (unit.casefolded in UNIT_DAYS) {
- set_rrule_daily(interval);
-
- return true;
- }
+ if (unit.casefolded in UNIT_DAYS)
+ return set_rrule_daily(interval);
// "weekday"
- if (unit.casefolded in UNIT_WEEKDAYS) {
- set_rrule_weekly(Calendar.DayOfWeek.weekdays, interval);
-
- return true;
- }
+ if (unit.casefolded in UNIT_WEEKDAYS)
+ return set_rrule_weekly(Calendar.DayOfWeek.weekdays, interval);
// "weekend"
- if (unit.casefolded in UNIT_WEEKENDS) {
- set_rrule_weekly(Calendar.DayOfWeek.weekend_days, interval);
-
- return true;
- }
+ if (unit.casefolded in UNIT_WEEKENDS)
+ return set_rrule_weekly(Calendar.DayOfWeek.weekend_days, interval);
// if no start date, then parse for start date, and if so, treat as yearly event
if (start_date == null) {
@@ -587,11 +573,8 @@ public class DetailsParser : BaseObject {
if (date == null)
date = parse_day_month(second, unit);
- if (date != null) {
- set_rrule_yearly(date, interval);
-
- return true;
- }
+ if (date != null)
+ return set_rrule_yearly(date, interval);
}
}
stack.restore();
@@ -600,9 +583,27 @@ public class DetailsParser : BaseObject {
return false;
}
- private void set_rrule_daily(int interval) {
+ // Using the supplied by days, find the first upcoming start_date that matches one of them
+ // that is also the week number (unless zero, which means "any")
+ private void set_byday_start_date(Calendar.DayOfWeek[]? by_days, int week_no) {
+ // find the earliest date in the by_days; if it's earlier than the start_date or the
+ // start_date isn't defined, use the earliest
+ if (by_days != null) {
+ Calendar.Date earliest = Calendar.System.today.upcoming_in_set(
+ from_array<Calendar.DayOfWeek>(by_days).to_hash_set(), true);
+ if (start_date == null || earliest.compare_to(start_date) < 0)
+ start_date = earliest;
+ }
+
+ // no start_date at this point, then today is it
+ if (start_date == null)
+ start_date = Calendar.System.today;
+ }
+
+ // "every day"
+ private bool set_rrule_daily(int interval) {
if (rrule != null)
- return;
+ return false;
// no start_date at this point, then today is it
if (start_date == null)
@@ -611,45 +612,59 @@ public class DetailsParser : BaseObject {
rrule = new RecurrenceRule(iCal.icalrecurrencetype_frequency.DAILY_RECURRENCE);
rrule.interval = interval;
rrule.first_of_week = Calendar.System.first_of_week.as_day_of_week();
+
+ return true;
}
- private void set_rrule_weekly(Calendar.DayOfWeek[]? by_days, int interval) {
- Gee.Map<Calendar.DayOfWeek?, int> map = new Gee.HashMap<Calendar.DayOfWeek?, int>();
- if (by_days != null) {
- foreach (Calendar.DayOfWeek by_day in by_days)
- map.set(by_day, 0);
- }
-
+ // "every tuesday"
+ private bool set_rrule_weekly(Calendar.DayOfWeek[]? by_days, int interval) {
if (rrule == null) {
rrule = new RecurrenceRule(iCal.icalrecurrencetype_frequency.WEEKLY_RECURRENCE);
rrule.interval = interval;
rrule.first_of_week = Calendar.System.first_of_week.as_day_of_week();
- rrule.set_by_rule(RecurrenceRule.ByRule.DAY, RecurrenceRule.encode_days(map));
- } else {
- rrule.add_by_rule(RecurrenceRule.ByRule.DAY, RecurrenceRule.encode_days(map));
+ } else if (!rrule.is_weekly) {
+ return false;
}
- // find the earliest date in the by_days; if it's earlier than the start_date or the
- // start_date isn't defined, use the earliest
- if (by_days != null) {
- Calendar.Date earliest = Calendar.System.today.upcoming_in_set(
- from_array<Calendar.DayOfWeek>(by_days).to_hash_set(), true);
- if (start_date == null || earliest.compare_to(start_date) < 0)
- start_date = earliest;
+ Gee.Map<Calendar.DayOfWeek?, int> map = from_array<Calendar.DayOfWeek>(by_days)
+ .to_hash_map_as_keys<int>(dow => 0);
+ rrule.add_by_rule(RecurrenceRule.ByRule.DAY, RecurrenceRule.encode_days(map));
+
+ set_byday_start_date(by_days);
+
+ return true;
+ }
+
+ // "every first tuesday"
+ private bool set_rrule_nth_day_of_week(Calendar.DayOfWeek[]? by_days, int week_no) {
+ if (rrule == null) {
+ rrule = new RecurrenceRule(iCal.icalrecurrencetype_frequency.MONTHLY_RECURRENCE);
+ rrule.first_of_week = Calendar.System.first_of_week.as_day_of_week();
+ } else if (!rrule.is_monthly) {
+ return false;
}
+ Gee.Map<Calendar.DayOfWeek?, int> map = from_array<Calendar.DayOfWeek>(by_days)
+ .to_hash_map_as_keys<int>(dow => 0);
+ rrule.add_by_rule(RecurrenceRule.ByRule.DAY, RecurrenceRule.encode_days(map));
- // no start_date at this point, then today is it
- if (start_date == null)
- start_date = Calendar.System.today;
+ set_byday_start_date(by_days);
+
+ return true;
}
- private void set_rrule_yearly(Calendar.Date date, int interval) {
+ // "every july 4th"
+ private bool set_rrule_yearly(Calendar.Date date, int interval) {
+ if (rrule != null)
+ return false;
+
start_date = date;
rrule = new RecurrenceRule(iCal.icalrecurrencetype_frequency.YEARLY_RECURRENCE);
rrule.interval = interval;
rrule.first_of_week = Calendar.System.first_of_week.as_day_of_week();
rrule.set_by_rule(RecurrenceRule.ByRule.YEAR_DAY, iterate<int>(date.day_of_year).to_array_list());
+
+ return true;
}
// Adds the text to the summary and location field, if adding_location is set
diff --git a/src/tests/tests-quick-add-recurring.vala b/src/tests/tests-quick-add-recurring.vala
index 8478dca..acb6ac1 100644
--- a/src/tests/tests-quick-add-recurring.vala
+++ b/src/tests/tests-quick-add-recurring.vala
@@ -34,6 +34,9 @@ private class QuickAddRecurring : UnitTest.Harness {
add_case("every-tuesday-thursday", every_tuesday_thursday);
add_case("every-tuesday-and-thursday", every_tuesday_and_thursday);
add_case("every-tuesday-and-thursday-for-3-weeks", every_tuesday_and_thursday_for_3_weeks);
+
+ // MONTHLY
+ add_case("every-first-tuesday", every_first_tuesday);
}
protected override void setup() throws Error {
@@ -237,8 +240,6 @@ private class QuickAddRecurring : UnitTest.Harness {
if (!Component.RecurrenceRule.decode_day(value, out dow, out position))
return false;
- debug("value %d -> %s %d", value, (dow != null) ? dow.to_string() : "null", position);
-
if (!by_days.has_key(dow) || by_days.get(dow) != position)
return false;
}
@@ -353,6 +354,24 @@ private class QuickAddRecurring : UnitTest.Harness {
&& check_byrule_day(event, by_days)
&& event.rrule.count == 3;
}
+
+ //
+ // MONTHLY
+ //
+
+ private bool every_first_tuesday(out string? dump) throws Error {
+ Gee.Map<Calendar.DayOfWeek?, int> by_days = iterate<Calendar.DayOfWeek?>(
+ Calendar.DayOfWeek.TUE).to_hash_map_as_keys<int>(dow => 1);
+
+ Component.Event event;
+ return basic("meeting at work at 10am every 1st tuesday", out event, out dump)
+ && event.rrule.is_monthly
+ && event.rrule.interval == 1
+ && !event.rrule.has_duration
+ && event.exact_time_span.start_date.day_of_week.equal_to(Calendar.DayOfWeek.TUE)
+ && event.exact_time_span.start_date.day_of_month.value <= 7
+ && check_byrule_day(event, by_days);
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]