[notmuch] [PATCH] Make the date parser nicer
Sebastian Spaeth
Sebastian at SSpaeth.de
Sun Jan 24 06:13:53 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 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 at 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
More information about the notmuch
mailing list