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 some formats. So a notmuch show date:2005..2006-05-12 will find all mails from 2005-01-01 until 2006-05-12. The code is probably not in a proper location yet and needs to be shoved around by someone more knowledgable than me. My C++ skills are somewhat,... lacking... Possible time formats: YYYY-MM-DD,YYYY-MM (in that month) , YYYY (in that year) MM-DD (month-day in current year), DD (day in current month) Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> --- lib/database.cc | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 89 insertions(+), 1 deletions(-) diff --git a/lib/database.cc b/lib/database.cc index 5b12320..9c2842d 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -494,6 +494,94 @@ _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 begin date to time_t + // possible time formats: + // YYYY-MM-DD (size 10) + // YYYY-MM (size 7) + // YYYY (size 4) + // MM-DD (size 5) + // DD (size 2) + // begin of time unit when 'early', end of when not + struct tm *timeinfo; + time_t timet; + //const char * startptr; + int year = 0, month = 0, day = 0; + + if (str.size() == 2) { + // parse day, then remove it from the string + day = atoi(str.c_str()); + str.erase(0,2); + } + + if (str.size() == 4 or str.size() == 7 or str.size() == 10) { + // parse year, then remove it from the string + year = atoi(str.c_str()); + str.erase(0,5); + } + + month = atoi(str.c_str()); + str.erase(0,3); + + // Do we have a day component left? + if (str.size()) + day = atoi(str.c_str()); + + if (year == 0 && month == 0 && day == 0) + // no expected time format + return NULL ; + + timet = time(NULL); + timeinfo = gmtime( &timet ); + timeinfo -> tm_isdst = 0; + if (!early && !month) ++year; + if (year) timeinfo -> tm_year = year - 1900; + + if (month) timeinfo -> tm_mon = month - 1; + //else if (year) timeinfo -> tm_mon = (early ? 0: 12); + + if (day) timeinfo -> tm_mday = (early ? day : ++day); + else timeinfo -> tm_mday = 1; + + timeinfo -> tm_hour = 0; + timeinfo -> tm_min = 0; + timeinfo -> tm_sec = 0; + timet = mktime ( timeinfo ); + + if (!early) --timet; + if (timet == -1) + return NULL; + 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); + if (begintime == -1) + // no valid time format + return Xapian::BAD_VALUENO; + + endtime = parsedate ( end, false); + if (endtime == -1) + // 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,7 +658,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, "date:", true); + 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