[notmuch] [PATCH] Make the date parser nicer. This is v3 and considered to be final (but the documentation).
Sebastian Spaeth
Sebastian at SSpaeth.de
Mon Jan 25 02:50:34 PST 2010
Currently we have to enter mail dates as timestamps. This approach does 2 things:
1) it requires the prefix 'date:'
2) it allows dates to be specified in a flexible way. So a notmuch show date:2005..2006-05-12 will find all mails from 2005-01-01 until 2006-05-12.
Possible time formats: YYYY-MM-DD, YYYY-MM (from/through that month) , YYYY (from/through that year), MM-DD (month-day in current year), DD (day in current month).
Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
lib/database.cc | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 79 insertions(+), 1 deletions(-)
diff --git a/lib/database.cc b/lib/database.cc
index 5b12320..da2fda8 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -494,6 +494,84 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch)
return NOTMUCH_STATUS_SUCCESS;
}
+struct MaildateValueRangeProcessor : public Xapian::ValueRangeProcessor {
+ MaildateValueRangeProcessor() {}
+
+ time_t
+ parsedate(std::string &str, bool early) {
+ /* Parse the date to a 'time_t', return NULL on error */
+ /* possible time formats: YYYY-MM-DD, YYYY-MM, YYYY, */
+ /* MM-DD (current month), DD (day in current month). */
+ /* Uses start of time unit when 'early', end otherwise, e.g. */
+ /* 2001:=2001-01-01:00:00:00 when 'early' or 2001-12-31:23:59:59 */
+ struct tm *timeinfo;
+ time_t timet;
+ int year = 0, month = 0, day = 0;
+
+ if (str.size() == 2) {
+ /* We got just current day in month, parse & remove it */
+ day = atoi(str.c_str());
+ str.erase(0,2);
+ }
+
+ if (str.size() == 4 or str.size() > 5) {
+ /* expect a year, parse & remove it */
+ year = atoi(str.c_str());
+ str.erase(0,5);
+ }
+
+ /* parse & remove month if there is sth left in the string */
+ month = atoi(str.c_str());
+ str.erase(0,3);
+
+ /* Parse day if we have one left */
+ if (str.size())
+ day = atoi(str.c_str());
+
+ if (year == 0 && month == 0 && day == 0)
+ // no expected time format
+ return -1 ;
+
+ timet = time(NULL); /* init timeinfo with current time */
+ timeinfo = gmtime(&timet);
+ /* add timeunit if !early (1 second too much, which we deduct later */
+ if (!early) {
+ if (year && !month) ++year; /* only year given */
+ if (year && month && !day) ++month; /* year & month given */
+ }
+ if (year) timeinfo -> tm_year = year - 1900;
+ if (month) timeinfo -> tm_mon = month - 1;
+ if (day) timeinfo -> tm_mday = (early ? day : ++day);
+ else timeinfo -> tm_mday = 1;
+
+ timeinfo -> tm_hour = 0;
+ timeinfo -> tm_min = 0;
+ timeinfo -> tm_sec = (early ? 0 : -1); /* -1 sec if !early */
+ timet = mktime(timeinfo);
+
+ return timet;
+ }
+
+ Xapian::valueno operator()(std::string &begin, std::string &end) {
+ time_t begintime, endtime;
+
+ if (begin.substr(0, 5) != "date:")
+ return Xapian::BAD_VALUENO;
+ begin.erase(0, 5);
+
+ begintime = parsedate(begin, true);
+ endtime = parsedate(end, false);
+ if ((begintime == -1) || (endtime == -1))
+ // parsedate failed, no valid time format
+ return Xapian::BAD_VALUENO;
+
+ begin.assign(Xapian::sortable_serialise(begintime));
+ end.assign(Xapian::sortable_serialise(endtime));
+
+ return NOTMUCH_VALUE_TIMESTAMP;
+ }
+};
+
notmuch_database_t *
notmuch_database_open (const char *path,
notmuch_database_mode_t mode)
@@ -570,8 +648,7 @@ notmuch_database_open (const char *path,
notmuch->query_parser = new Xapian::QueryParser;
notmuch->term_gen = new Xapian::TermGenerator;
notmuch->term_gen->set_stemmer (Xapian::Stem ("english"));
- notmuch->value_range_processor = new Xapian::NumberValueRangeProcessor (NOTMUCH_VALUE_TIMESTAMP);
+ notmuch->value_range_processor = new MaildateValueRangeProcessor();
notmuch->query_parser->set_default_op (Xapian::Query::OP_AND);
notmuch->query_parser->set_database (*notmuch->xapian_db);
--
1.6.3.3
More information about the notmuch
mailing list