 ;;; +-------------------------------------------------------------------------------------------------------+
 
 
+(defn- relative-date->range
+  "Take a given string description of a relative date range such as 'lastmonth' and return a MAP with a given
+   `:start` and `:end` as iso8601 string formatted dates.  Values should be appropriate for the given REPORT-TIMEZONE."
+  [value report-timezone]
+  (let [tz        (t/time-zone-for-id report-timezone)
+        formatter (tf/formatter "YYYY-MM-dd" tz)
+        today     (t/today-at-midnight tz)]
+    (->> (condp = value
+           "past7days"  {:end   (t/minus today (t/days 1))
+                         :start (t/minus today (t/days 7))}
+           "past30days" {:end   (t/minus today (t/days 1))
+                         :start (t/minus today (t/days 30))}
+           "thisweek"   (week-range today)
+           "thismonth"  (month-range today)
+           "thisyear"   (year-range today)
+           "lastweek"   (week-range (t/minus today (t/weeks 1)))
+           "lastmonth"  (month-range (t/minus today (t/months 1)))
+           "lastyear"   (year-range (t/minus today (t/years 1)))
+           "yesterday"  {:end   (t/minus today (t/days 1))
+                         :start (t/minus today (t/days 1))}
+           "today"      {:end   today
+                         :start today})
+         ;; the above values are JodaTime objects, so unparse them to iso8601 strings
+         (m/map-vals (partial tf/unparse formatter)))))
+
 (defn- extract-dates [value report-timezone]
   (if-not (contains? relative-dates value)
-    ;; absolute date range such as: "2014-05-10,2014-05-16"
-    ;; TODO: other absolute options?  year-quarter?  year-month?
-    (zipmap [:start :end] (s/split value #"~" 2))
+    ;; absolute date range
+    (absolute-date->range value)
     ;; relative date range
-    (let [tz        (t/time-zone-for-id report-timezone)
-          formatter (tf/formatter "YYYY-MM-dd" tz)
-          today     (t/today-at-midnight tz)]
-      (->> (condp = value
-             "past7days"  {:end   (t/minus today (t/days 1))
-                           :start (t/minus today (t/days 7))}
-             "past30days" {:end   (t/minus today (t/days 1))
-                           :start (t/minus today (t/days 30))}
-             "yesterday"  {:end   (t/minus today (t/days 1))
-                           :start (t/minus today (t/days 1))}
-             "today"      {:end   today
-                           :start today})
-           ;; the above values are JodaTime objects, so unparse them to iso8601 strings
-           (m/map-vals (partial tf/unparse formatter))))))
+    (relative-date->range value report-timezone)))
 
 (defn- expand-date-range-param [report-timezone {[target param-name] :target, param-type :type, param-value :value, :as param}]
   (if-not (= param-type "date")

            [clj-time.core :as t]
            [clj-time.format :as tf]
            [medley.core :as m]
            [metabase.driver :as driver]))


(def ^:private ^:const relative-dates
  #{"today"
    "yesterday"
    "past7days"
    "past30days"})


;;; +-------------------------------------------------------------------------------------------------------+

    ["=" field param-value]
    ;; otherwise we need to handle date filtering
    (if-not (contains? relative-dates param-value)
      ;; absolute date range
      (let [{:keys [start end]} (absolute-date->range param-value)]
        ["BETWEEN" field start end])
      ;; relative date range
      (condp = param-value
        "past7days"  ["TIME_INTERVAL" field -7 "day"]
        "past30days" ["TIME_INTERVAL" field -30 "day"]
        "thisweek"   ["TIME_INTERVAL" field "current" "week"]
        "thismonth"  ["TIME_INTERVAL" field "current" "month"]
        "thisyear"   ["TIME_INTERVAL" field "current" "year"]
        "lastweek"   ["TIME_INTERVAL" field "last" "week"]
        "lastmonth"  ["TIME_INTERVAL" field "last" "month"]
        "lastyear"   ["TIME_INTERVAL" field "last" "year"]
        "yesterday"  ["=" field ["relative_datetime" -1 "day"]]
        "today"      ["=" field ["relative_datetime" "current"]]))))

