[california/wip/725785-create-recurring] Revised Date.upcoming/prior, nth day of week (of month) now works
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/725785-create-recurring] Revised Date.upcoming/prior, nth day of week (of month) now works
- Date: Fri, 20 Jun 2014 23:36:02 +0000 (UTC)
commit 5296060d2b251ea077f67760b21a4f8a983a4eab
Author: Jim Nelson <jim yorba org>
Date: Fri Jun 20 16:35:32 2014 -0700
Revised Date.upcoming/prior, nth day of week (of month) now works
src/calendar/calendar-date.vala | 62 ++++++-----------------
src/calendar/calendar-week.vala | 3 +
src/component/component-details-parser.vala | 28 +++++++---
src/tests/tests-calendar-date.vala | 72 ++++++++++++++++++++++-----
src/tests/tests-quick-add-recurring.vala | 2 +-
src/tests/tests-quick-add.vala | 3 +-
src/tests/tests.vala | 4 +-
7 files changed, 103 insertions(+), 71 deletions(-)
---
diff --git a/src/calendar/calendar-date.vala b/src/calendar/calendar-date.vala
index e9b90d1..9f0e71f 100644
--- a/src/calendar/calendar-date.vala
+++ b/src/calendar/calendar-date.vala
@@ -256,67 +256,35 @@ public class Date : Unit<Date>, Gee.Comparable<Date>, Gee.Hashable<Date> {
}
/**
- * Returns the { link Date} of the upcoming (next chronological) { link DayOfWeek}.
+ * Returns the { link Date} of the upcoming (next chronological) Date that matches
+ * the predicate's requirements.
*
- * Set { link includes_this_day} to true if this Date is to be considered "upcoming", that is,
- * if it falls on the day of the week, it is returned.
+ * inclusive indicates if this Date is included in the search.
*
* @see prior
*/
- public Date upcoming(DayOfWeek dow, bool includes_this_day) {
- return upcoming_prior(iterate<DayOfWeek>(dow).to_hash_set(), includes_this_day, 1);
+ public Date upcoming(bool inclusive, Gee.Predicate<Calendar.Date> predicate) {
+ return upcoming_prior(inclusive, 1, predicate);
}
/**
- * Returns the { link Date} of the upcoming (next chronological) { link DayOfWeek} from the
- * set provided.
+ * Returns the { link Date} of the prior (next chronological) Date that matches
+ * the predicate's requirements.
*
- * Set { link includes_this_day} to true if this Date is to be considered "upcoming", that is,
- * if it falls on the day of the week, it is returned.
- *
- * @see prior_in_set
- */
- public Date upcoming_in_set(Gee.Set<DayOfWeek> dow_set, bool includes_this_day) {
- return upcoming_prior(dow_set, includes_this_day, 1);
- }
-
- /**
- * Returns the { link Date} of the prior (previous chronological) { link DayOfWeek}.
- *
- * Set { link includes_this_day} to true if this Date is to be considered "prior", that is,
- * if it falls on the day of the week, it is returned.
+ * inclusive indicates if this Date is included in the search.
*
* @see upcoming
*/
- public Date prior(DayOfWeek dow, bool includes_this_day) {
- return upcoming_prior(iterate<DayOfWeek>(dow).to_hash_set(), includes_this_day, -1);
- }
-
- /**
- * Returns the { link Date} of the prior (next chronological) { link DayOfWeek} from the
- * set provided.
- *
- * Set { link includes_this_day} to true if this Date is to be considered "prior", that is,
- * if it falls on the day of the week, it is returned.
- *
- * @see upcoming_in_set
- */
- public Date prior_in_set(Gee.Set<DayOfWeek> dow_set, bool includes_this_day) {
- return upcoming_prior(dow_set, includes_this_day, -1);
+ public Date prior(bool inclusive, Gee.Predicate<Calendar.Date> predicate) {
+ return upcoming_prior(inclusive, -1, predicate);
}
- private Date upcoming_prior(Gee.Set<DayOfWeek> dow_set, bool includes_this_day, int adjustment) {
- // look for current date being the one
- if (dow_set.contains(day_of_week) && includes_this_day)
- return this;
+ private Date upcoming_prior(bool inclusive, int adjustment, Gee.Predicate<Calendar.Date> predicate) {
+ Calendar.Date current = inclusive ? this : adjust(adjustment);
+ while (!predicate(current))
+ current = current.adjust(adjustment);
- // find a Date for day of the week ... brute force isn't great, but it works
- Date upcoming_prior = this;
- for (;;) {
- upcoming_prior = upcoming_prior.adjust(adjustment);
- if (dow_set.contains(upcoming_prior.day_of_week))
- return upcoming_prior;
- }
+ return current;
}
/**
diff --git a/src/calendar/calendar-week.vala b/src/calendar/calendar-week.vala
index 2ff35a0..65f3eaa 100644
--- a/src/calendar/calendar-week.vala
+++ b/src/calendar/calendar-week.vala
@@ -19,6 +19,9 @@ namespace California.Calendar {
*/
public class Week : Unit<Week>, Gee.Comparable<Week>, Gee.Hashable<Week> {
+ public const int MIN_WEEK_OF_MONTH = 1;
+ public const int MAX_WEEK_OF_MONTH = 6;
+
/**
* The one-based week of the month (1 to 6).
*/
diff --git a/src/component/component-details-parser.vala b/src/component/component-details-parser.vala
index e5ee3cc..88133ae 100644
--- a/src/component/component-details-parser.vala
+++ b/src/component/component-details-parser.vala
@@ -541,8 +541,7 @@ public class DetailsParser : BaseObject {
// a day of the week
Calendar.DayOfWeek? dow = Calendar.DayOfWeek.parse(unit.casefolded);
if (dow != null) {
- Calendar.DayOfWeek[] by_days = iterate<Calendar.DayOfWeek>(
- Calendar.System.today.upcoming(dow, true).day_of_week).to_array();
+ Calendar.DayOfWeek[] by_days = iterate<Calendar.DayOfWeek>(dow).to_array();
// if interval is an ordinal, the rule is for "nth day of the month", so it's a week number
if (!is_ordinal)
@@ -589,8 +588,13 @@ public class DetailsParser : BaseObject {
// 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);
+ Gee.Set<Calendar.DayOfWeek> dows = from_array<Calendar.DayOfWeek>(by_days).to_hash_set();
+ Calendar.Date earliest = Calendar.System.today.upcoming(true, (date) => {
+ if (week_no != 0 && date.week_of(Calendar.System.first_of_week).week_of_month != week_no)
+ return false;
+
+ return dows.contains(date.day_of_week);
+ });
if (start_date == null || earliest.compare_to(start_date) < 0)
start_date = earliest;
}
@@ -630,24 +634,30 @@ public class DetailsParser : BaseObject {
.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);
+ set_byday_start_date(by_days, 0);
return true;
}
// "every first tuesday"
private bool set_rrule_nth_day_of_week(Calendar.DayOfWeek[]? by_days, int week_no) {
+ // Although a month can span 6 calendar weeks, a day of a week never appears in more than
+ // five of them
+ if (week_no < 1 || week_no > 5)
+ return false;
+
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);
+ .to_hash_map_as_keys<int>(dow => week_no);
rrule.add_by_rule(RecurrenceRule.ByRule.DAY, RecurrenceRule.encode_days(map));
- set_byday_start_date(by_days);
+ set_byday_start_date(by_days, week_no);
return true;
}
@@ -713,7 +723,9 @@ public class DetailsParser : BaseObject {
// attempt to parse into day of the week
Calendar.DayOfWeek? dow = Calendar.DayOfWeek.parse(token.casefolded);
- return (dow != null) ? Calendar.System.today.upcoming(dow, true) : null;
+ return (dow != null)
+ ? Calendar.System.today.upcoming(true, date => date.day_of_week.equal_to(dow))
+ : null;
}
// Parses potential date specifiers into a specific calendar date
diff --git a/src/tests/tests-calendar-date.vala b/src/tests/tests-calendar-date.vala
index 0291696..2d3b085 100644
--- a/src/tests/tests-calendar-date.vala
+++ b/src/tests/tests-calendar-date.vala
@@ -14,8 +14,10 @@ private class CalendarDate : UnitTest.Harness {
add_case("clamp-neither", clamp_neither);
add_case("difference-pos", difference_pos);
add_case("difference-neg", difference_neg);
- add_case("upcoming", upcoming);
- add_case("prior", prior);
+ add_case("upcoming-inclusive", upcoming_inclusive);
+ add_case("upcoming-exclusive", upcoming_exclusive);
+ add_case("prior-inclusive", prior_inclusive);
+ add_case("prior-exclusive", prior_exclusive);
add_case("upcoming-today", upcoming_today);
add_case("upcoming-next-week", upcoming_next_week);
}
@@ -82,25 +84,70 @@ private class CalendarDate : UnitTest.Harness {
return today.difference(day_before_yesterday) == -2;
}
- private bool upcoming() throws Error {
+ private bool upcoming(bool inclusive, out string? dump) throws Error {
+ dump = null;
+
Calendar.Date today = Calendar.System.today;
- Calendar.Date upcoming_fri = today.upcoming(Calendar.DayOfWeek.FRI, false);
- int diff = today.difference(upcoming_fri);
- return diff > 0 && diff <= 7;
+ foreach (Calendar.DayOfWeek dow in Calendar.DayOfWeek.all(Calendar.FirstOfWeek.SUNDAY)) {
+ Calendar.Date upcoming = Calendar.System.today.upcoming(inclusive,
+ date => date.day_of_week.equal_to(dow));
+ int diff = today.difference(upcoming);
+
+ dump = "%s - %s = %d".printf(today.to_string(), upcoming.to_string(), diff);
+
+ if (!inclusive && diff == 0)
+ return false;
+
+ if (diff < 0 || diff > 7)
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool upcoming_inclusive(out string? dump) throws Error {
+ return upcoming(true, out dump);
+ }
+
+ private bool upcoming_exclusive(out string? dump) throws Error {
+ return upcoming(false, out dump);
}
- private bool prior() throws Error {
+ private bool prior(bool inclusive, out string? dump) throws Error {
+ dump = null;
+
Calendar.Date today = Calendar.System.today;
- Calendar.Date prior_tue = today.prior(Calendar.DayOfWeek.TUE, false);
- int diff = today.difference(prior_tue);
- return diff < 0 && diff >= -7;
+ foreach (Calendar.DayOfWeek dow in Calendar.DayOfWeek.all(Calendar.FirstOfWeek.SUNDAY)) {
+ Calendar.Date upcoming = Calendar.System.today.prior(inclusive,
+ date => date.day_of_week.equal_to(dow));
+ int diff = today.difference(upcoming);
+
+ dump = "%s - %s = %d".printf(today.to_string(), upcoming.to_string(), diff);
+
+ if (!inclusive && diff == 0)
+ return false;
+
+ if (diff > 0 || diff < -7)
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool prior_inclusive(out string? dump) throws Error {
+ return prior(false, out dump);
+ }
+
+ private bool prior_exclusive(out string? dump) throws Error {
+ return prior(false, out dump);
}
private bool upcoming_today() throws Error {
Calendar.Date today = Calendar.System.today;
- Calendar.Date another_today = today.upcoming(today.day_of_week, true);
+ Calendar.Date another_today = today.upcoming(true,
+ date => date.day_of_week.equal_to(today.day_of_week));
int diff = today.difference(another_today);
return diff == 0;
@@ -108,7 +155,8 @@ private class CalendarDate : UnitTest.Harness {
private bool upcoming_next_week() throws Error {
Calendar.Date today = Calendar.System.today;
- Calendar.Date next_week = today.upcoming(today.day_of_week, false);
+ Calendar.Date next_week = today.upcoming(false,
+ date => date.day_of_week.equal_to(today.day_of_week));
int diff = today.difference(next_week);
return diff == 7;
diff --git a/src/tests/tests-quick-add-recurring.vala b/src/tests/tests-quick-add-recurring.vala
index acb6ac1..07879d8 100644
--- a/src/tests/tests-quick-add-recurring.vala
+++ b/src/tests/tests-quick-add-recurring.vala
@@ -152,7 +152,7 @@ private class QuickAddRecurring : UnitTest.Harness {
Component.DetailsParser parser = new Component.DetailsParser(details, null);
event = parser.event;
- dump = event.source;
+ dump = "%s\n%s".printf(details, event.source);
return event.rrule != null
&& event.summary == "meeting at work"
diff --git a/src/tests/tests-quick-add.vala b/src/tests/tests-quick-add.vala
index 0972812..b111d41 100644
--- a/src/tests/tests-quick-add.vala
+++ b/src/tests/tests-quick-add.vala
@@ -179,7 +179,8 @@ private class QuickAdd : UnitTest.Harness {
Component.DetailsParser parser = new Component.DetailsParser(
"12:30pm Friday Lunch with Eric and Charles", null);
- Calendar.Date friday = Calendar.System.today.upcoming(Calendar.DayOfWeek.FRI, true);
+ Calendar.Date friday = Calendar.System.today.upcoming(true,
+ date => date.day_of_week.equal_to(Calendar.DayOfWeek.FRI));
Calendar.ExactTime start = new Calendar.ExactTime(Calendar.Timezone.local, friday,
new Calendar.WallTime(12, 30, 0));
diff --git a/src/tests/tests.vala b/src/tests/tests.vala
index 0f88f76..22b3579 100644
--- a/src/tests/tests.vala
+++ b/src/tests/tests.vala
@@ -8,12 +8,12 @@ namespace California.Tests {
public int run(string[] args) {
UnitTest.Harness.register(new String());
- UnitTest.Harness.register(new QuickAdd());
- UnitTest.Harness.register(new QuickAddRecurring());
UnitTest.Harness.register(new CalendarDate());
UnitTest.Harness.register(new CalendarMonthSpan());
UnitTest.Harness.register(new CalendarMonthOfYear());
UnitTest.Harness.register(new CalendarWallTime());
+ UnitTest.Harness.register(new QuickAdd());
+ UnitTest.Harness.register(new QuickAddRecurring());
return UnitTest.Harness.exec_all();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]