summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRicardo Wurmus <rekado@elephly.net>2018-09-03 13:41:04 +0200
committerRicardo Wurmus <rekado@elephly.net>2018-09-03 13:41:04 +0200
commit1f8c863f19ba7dab06ca9db14c60ccfe2408d04f (patch)
treec4420c308461fc2e887353371a76b845f6fac072
parent2949dce3cc417d44ea2d398d443b39f0f6e8057f (diff)
process-query: Support date filtering.
* mumi/messages.scm (ago, date-term->epoch-seconds): New procedures. (process-query): Support "date" and "mdate" queries.
-rw-r--r--mumi/messages.scm69
1 files changed, 69 insertions, 0 deletions
diff --git a/mumi/messages.scm b/mumi/messages.scm
index 00f80fd..5110de9 100644
--- a/mumi/messages.scm
+++ b/mumi/messages.scm
@@ -331,6 +331,48 @@ of message parts."
matches)) amount)))
(soap-invoke* (%config 'debbugs) get-status ids)))
+(define (ago unit amount)
+ "Return the point in time that lies AMOUNT UNITs in the past."
+ (let ((amount* (match unit
+ ('hours amount)
+ ('days (* 24 amount))
+ ('weeks (* 24 7 amount))
+ ('months (* 24 30 amount))
+ ('years (* 24 365 amount)))))
+ (subtract-duration (date->time-utc (current-date))
+ (make-time time-duration 0 (* 60 60 amount*)))))
+
+(define (date-term->epoch-seconds term)
+ "Convert a date search term string into seconds since the epoch, or
+return #F if the term is invalid."
+ (match term
+ ("now" 'now)
+ ("today" (time-second (ago 'days 1)))
+ ("yesterday" (time-second (ago 'days 2)))
+ (_
+ (cond
+ ;; TODO: support more date template strings
+ ((or (false-if-exception (string->date term "~Y~m~d"))
+ (false-if-exception (string->date term "~Y-~m-~d")))
+ => (lambda (date)
+ (time-second (date->time-utc date))))
+ ;; e.g. "12h" meaning "12 hours ago"
+ ((string->number (string-drop-right term 1))
+ => (lambda (amount)
+ (match (string-take-right term 1)
+ ("h"
+ (time-second (ago 'hours amount)))
+ ("d"
+ (time-second (ago 'days amount)))
+ ("w"
+ (time-second (ago 'weeks amount)))
+ ("m"
+ (time-second (ago 'months amount)))
+ ("y"
+ (time-second (ago 'years amount)))
+ (_ #f))))
+ (else #f)))))
+
(define-public (process-query query)
"Process the QUERY string and return two values: the remaining
unprocessed query string and an alist of search attributes."
@@ -352,6 +394,33 @@ unprocessed query string and an alist of search attributes."
#:attributes ,attrs
#:filters
,(cons (negate bug-done) fs)))
+ ;; "date" for submission date, "mdate" for message date.
+ (((and (or "date" "mdate") type) when)
+ (let ((date-attribute (match type
+ ("date" 'date)
+ ("mdate" '@cdate)))
+ (pat "(yesterday|today|now|[1-9][0-9]*(h|d|w|m|y)|[0-9]+)"))
+ (or (match (map (compose date-term->epoch-seconds
+ match:substring)
+ (list-matches pat when))
+ ((and ((? number? start)
+ (? number? end))
+ range)
+ (match (sort range <)
+ ((start end)
+ `(#:terms ,terms
+ #:attributes ,(cons `(,date-attribute >< ,start ,end) attrs)
+ #:filters ,fs))))
+ ((or ('now (? number? since))
+ ((? number? since) 'now))
+ `(#:terms ,terms
+ #:attributes ,(cons `(,date-attribute > ,since) attrs)
+ #:filters ,fs))
+ (_ #f))
+ ;; Invalid, don't do anything.
+ `(#:terms ,terms
+ #:attributes ,attrs
+ #:filters ,fs))))
(("title" title)
`(#:terms ,terms
#:attributes ,(cons `(subject string-contains ,title) attrs)