[california] Support time ranges with Quick Add: Bug #731485
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Support time ranges with Quick Add: Bug #731485
- Date: Fri, 15 Aug 2014 02:10:33 +0000 (UTC)
commit 7db54944dae373afadc7adf4b3789c94606abcaf
Author: Jim Nelson <jim yorba org>
Date: Thu Aug 14 19:09:59 2014 -0700
Support time ranges with Quick Add: Bug #731485
Time ranges w/ dashes ("6p-9p") now supported by Quick Add.
src/calendar/calendar-wall-time.vala | 18 +-------
src/calendar/calendar.vala | 31 ++++++++++++++
src/component/component-details-parser.vala | 61 +++++++++++++++++++++++++-
src/tests/tests-quick-add.vala | 58 +++++++++++++++++--------
4 files changed, 131 insertions(+), 37 deletions(-)
---
diff --git a/src/calendar/calendar-wall-time.vala b/src/calendar/calendar-wall-time.vala
index aaa8494..781a79b 100644
--- a/src/calendar/calendar-wall-time.vala
+++ b/src/calendar/calendar-wall-time.vala
@@ -150,22 +150,8 @@ public class WallTime : BaseObject, Gee.Comparable<WallTime>, Gee.Hashable<WallT
return new WallTime(12, 0, 0);
}
- // look for meridiem tacked on to end
- bool pm = false;
- bool meridiem_unknown = false;
- if (token.has_suffix(FMT_AM.casefold())) {
- token = token.slice(0, token.length - FMT_AM.casefold().length);
- } else if (token.has_suffix(FMT_BRIEF_AM.casefold())) {
- token = token.slice(0, token.length - FMT_BRIEF_AM.casefold().length);
- } else if (token.has_suffix(FMT_PM.casefold())) {
- token = token.slice(0, token.length - FMT_PM.casefold().length);
- pm = true;
- } else if (token.has_suffix(FMT_BRIEF_PM.casefold())) {
- token = token.slice(0, token.length - FMT_BRIEF_PM.casefold().length);
- pm = true;
- } else {
- meridiem_unknown = true;
- }
+ bool meridiem_unknown, pm;
+ token = parse_meridiem(token, out meridiem_unknown, out pm);
// remove colon (can be present for 12- or 24-hour time)
bool has_colon = token.index_of(":") > 0;
diff --git a/src/calendar/calendar.vala b/src/calendar/calendar.vala
index 25ae3f8..75cc426 100644
--- a/src/calendar/calendar.vala
+++ b/src/calendar/calendar.vala
@@ -258,4 +258,35 @@ public void terminate() {
Collection.terminate();
}
+/**
+ * Detects if the string has a meridiem prefix, either brief or full, depending on the locale.
+ *
+ * The string should be casefolded and stripped of leading and trailing whitespace.
+ *
+ * Returns the string with the meridiem stripped off as well as indicators about what was found,
+ * if anything. If no meridiem was found, the original string is returned.
+ */
+private string parse_meridiem(string str, out bool meridiem_unknown, out bool is_pm) {
+ meridiem_unknown = false;
+ is_pm = false;
+
+ string stripped;
+ if (str.has_suffix(FMT_AM.casefold())) {
+ stripped = str.slice(0, str.length - FMT_AM.casefold().length);
+ } else if (str.has_suffix(FMT_BRIEF_AM.casefold())) {
+ stripped = str.slice(0, str.length - FMT_BRIEF_AM.casefold().length);
+ } else if (str.has_suffix(FMT_PM.casefold())) {
+ stripped = str.slice(0, str.length - FMT_PM.casefold().length);
+ is_pm = true;
+ } else if (str.has_suffix(FMT_BRIEF_PM.casefold())) {
+ stripped = str.slice(0, str.length - FMT_BRIEF_PM.casefold().length);
+ is_pm = true;
+ } else {
+ stripped = str;
+ meridiem_unknown = true;
+ }
+
+ return stripped;
+}
+
}
diff --git a/src/component/component-details-parser.vala b/src/component/component-details-parser.vala
index bda7631..3f6b854 100644
--- a/src/component/component-details-parser.vala
+++ b/src/component/component-details-parser.vala
@@ -326,13 +326,25 @@ public class DetailsParser : BaseObject {
return add_date(saturday) && add_date(sunday);
}
- // look for fully numeric date specifier
+ // look for fully numeric date specifier (i.e. "7/2/14")
{
Calendar.Date? date = parse_numeric_date(specifier);
if (date != null && add_date(date))
return true;
}
+ // look for time range (i.e. "6p-9p", "6-9p")
+ {
+ Calendar.WallTime start, end;
+ bool strictly_parsed;
+ if (parse_time_range(specifier, out start, out end, out strictly_parsed)) {
+ if (!strict || (strict && strictly_parsed)) {
+ if (add_wall_time(start, strictly_parsed) && add_wall_time(end, strictly_parsed))
+ return true;
+ }
+ }
+ }
+
// look for day/month specifiers, in any order
stack.mark();
{
@@ -753,9 +765,9 @@ public class DetailsParser : BaseObject {
// punctuation removed
int a, b, c;
char[] separator = new char[token.original.length];
- if (token.original.scanf("%d%[/.-]%d%[/.-]%d", out a, separator, out b, separator, out c) == 5) {
+ if (token.original.scanf("%d%[/.]%d%[/.]%d", out a, separator, out b, separator, out c) == 5) {
// good to go
- } else if (token.original.scanf("%d%[/.-]%d", out a, separator, out b) == 3) {
+ } else if (token.original.scanf("%d%[/.]%d", out a, separator, out b) == 3) {
// -1 means two-number date was found, i.e. year must be determined manually
c = -1;
} else {
@@ -842,6 +854,49 @@ public class DetailsParser : BaseObject {
}
}
+ // strictly parsed means *both* were strictly parsed
+ private bool parse_time_range(Token token, out Calendar.WallTime start, out Calendar.WallTime end,
+ out bool strictly_parsed) {
+ start = null;
+ end = null;
+ strictly_parsed = false;
+
+ string[] separated = token.original.split("-");
+ if (separated.length != 2)
+ return false;
+
+ // fixup meridiems: if one has a specifier, assume for both
+
+ string start_string = separated[0].casefold().strip();
+ bool start_meridiem_unknown, is_start_pm;
+ Calendar.parse_meridiem(start_string, out start_meridiem_unknown, out is_start_pm);
+
+ string end_string = separated[1].casefold().strip();
+ bool end_meridiem_unknown, is_end_pm;
+ Calendar.parse_meridiem(end_string, out end_meridiem_unknown, out is_end_pm);
+
+ if (!start_meridiem_unknown && end_meridiem_unknown)
+ end_string += is_start_pm ? Calendar.FMT_PM : Calendar.FMT_AM;
+ else if (start_meridiem_unknown && !end_meridiem_unknown)
+ start_string += is_end_pm ? Calendar.FMT_PM : Calendar.FMT_AM;
+
+ // parse away
+
+ bool start_strictly_parsed;
+ start = Calendar.WallTime.parse(start_string, out start_strictly_parsed);
+ if (start == null)
+ return false;
+
+ bool end_strictly_parsed;
+ end = Calendar.WallTime.parse(end_string, out end_strictly_parsed);
+ if (end == null)
+ return false;
+
+ strictly_parsed = start_strictly_parsed && end_strictly_parsed;
+
+ return true;
+ }
+
// Parses a potential date specifier into a calendar date relative to today
private Calendar.Date? parse_relative_date(Token token) {
// attempt to parse into common words for relative dates
diff --git a/src/tests/tests-quick-add.vala b/src/tests/tests-quick-add.vala
index 19efdce..c902c37 100644
--- a/src/tests/tests-quick-add.vala
+++ b/src/tests/tests-quick-add.vala
@@ -45,11 +45,14 @@ private class QuickAdd : UnitTest.Harness {
add_case("numeric-mdyyyy", numeric_mdyyyy);
add_case("numeric-dmyyyy", numeric_dmyyyy);
add_case("numeric-dot", numeric_dot);
- add_case("numeric-dash", numeric_dash);
add_case("numeric-leading-zeros", numeric_leading_zeroes);
add_case("street-address_3", street_address_3);
add_case("street-address_3a", street_address_3a);
add_case("street-address_4", street_address_4);
+ add_case("time-range-both-meridiem", time_range_both_meridiem);
+ add_case("time-range-one-meridiem", time_range_one_meridiem);
+ add_case("time-range-24hr", time_range_24hr);
+ add_case("time-range-no-meridiem", time_range_no_meridiem);
}
protected override void setup() throws Error {
@@ -504,27 +507,11 @@ private class QuickAdd : UnitTest.Harness {
&& parser.event.date_span.start_date.year.value == 2014;
}
- private bool numeric_dash(out string? dump) throws Error {
- Calendar.System.date_ordering = Calendar.DateOrdering.MDY;
- Calendar.System.date_separator = "-";
- Component.DetailsParser parser = new Component.DetailsParser(
- "7-2-14 Offsite", null);
-
- dump = parser.event.source;
-
- return parser.event.summary == "Offsite"
- && parser.event.is_all_day
- && parser.event.date_span.duration.days == 1
- && parser.event.date_span.start_date.month == Calendar.Month.JUL
- && parser.event.date_span.start_date.day_of_month.value == 2
- && parser.event.date_span.start_date.year.value == 2014;
- }
-
private bool numeric_leading_zeroes(out string? dump) throws Error {
Calendar.System.date_ordering = Calendar.DateOrdering.MDY;
Calendar.System.date_separator = "/";
Component.DetailsParser parser = new Component.DetailsParser(
- "07-02-14 Offsite", null);
+ "07/02/14 Offsite", null);
dump = parser.event.source;
@@ -576,6 +563,41 @@ private class QuickAdd : UnitTest.Harness {
&& parser.event.exact_time_span.start_exact_time.hour == 18
&& parser.event.exact_time_span.start_exact_time.minute == 30;
}
+
+ private bool test_time_range(string details, out string? dump) throws Error {
+ Component.DetailsParser parser = new Component.DetailsParser(details, null);
+
+ dump = parser.event.source;
+
+ return parser.event.summary == "Opus Affair"
+ && !parser.event.is_all_day
+ && parser.event.exact_time_span.start_exact_time.hour == 18
+ && parser.event.exact_time_span.start_exact_time.minute == 0
+ && parser.event.exact_time_span.end_exact_time.hour == 21
+ && parser.event.exact_time_span.end_exact_time.minute == 0;
+ }
+
+ private bool time_range_both_meridiem(out string? dump) throws Error {
+ return test_time_range("6p-9p Opus Affair", out dump);
+ }
+
+ private bool time_range_one_meridiem(out string? dump) throws Error {
+ return test_time_range("6-9p Opus Affair", out dump);
+ }
+
+ private bool time_range_24hr(out string? dump) throws Error {
+ return test_time_range("18:00-21:00 Opus Affair", out dump);
+ }
+
+ private bool time_range_no_meridiem(out string? dump) throws Error {
+ Component.DetailsParser parser = new Component.DetailsParser(
+ "6-9 Opus Affair", null);
+
+ dump = parser.event.source;
+
+ return parser.event.summary == "6-9 Opus Affair"
+ && !parser.event.is_valid(false);
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]