diff --git a/deps/graph-parser/src/logseq/graph_parser/util/db.cljs b/deps/graph-parser/src/logseq/graph_parser/util/db.cljs index f790a5fb23..f5e3355eba 100644 --- a/deps/graph-parser/src/logseq/graph_parser/util/db.cljs +++ b/deps/graph-parser/src/logseq/graph_parser/util/db.cljs @@ -55,24 +55,28 @@ it will return 1622433600000, which is equivalent to Mon May 31 2021 00 :00:00." - ms: milliseconds, will return a time relative to the direction the date is being adjusted - start: will return the time at the start of the day [00:00:00] - end: will return the time at the end of the day [24:00:00] - - HHMM: will return the specified time at the turn of the minute [HH:MM:00] - " + - HHMM: will return the specified time at the turn of the minute [HH:MM:00]" [offset-direction offset-time] (case offset-time - "ms" (if (= offset-direction "+") [24 0] [0 0]) - "start" [0 0] - "end" [24 0] - :else [(parse-long (subs offset-time 0 2)) (parse-long (subs offset-time 2 4))])) + "ms" (if (= offset-direction "+") [23 59 59 999] [0 0 0 0]) + "start" [0 0 0 0] + "end" [23 59 59 999] + ;; if it's not a matching string, then assume it is HHMM + [(parse-long (subs offset-time 0 2)) (parse-long (subs offset-time 2 4)) 0 0])) (defn keyword-input-dispatch [input] (cond (#{:current-page :current-block :parent-block :today :yesterday :tomorrow :right-now-ms} input) input + (re-find #"^[+-]\d+[dwmy]?$" (name input)) :relative-date (re-find #"^[+-]\d+[dwmy]-(ms|start|end|\d\d\d\d)?$" (name input)) :relative-date-time - (re-find #"^today-(start|end|\d\d\d\d)$" (name input)) :today-time + (= :start-of-today-ms input) :today-time (= :end-of-today-ms input) :today-time + (re-find #"^today-(start|end|\d\d\d\d)$" (name input)) :today-time + (re-find #"^\d+d(-before|-after|-before-ms|-after-ms)?$" (name input)) :DEPRECATED-relative-date)) + (defmulti resolve-keyword-input (fn [_db input _opts] (keyword-input-dispatch input))) (defmethod resolve-keyword-input :current-page [_ _ {:keys [current-page-fn]}] @@ -99,25 +103,28 @@ it will return 1622433600000, which is equivalent to Mon May 31 2021 00 :00:00." (defmethod resolve-keyword-input :right-now-ms [_ _ _] (date-time-util/time-ms)) +;; today-time returns an epoch int (defmethod resolve-keyword-input :today-time [_db input _opts] - (let [[hour minute] (case input - :start-of-today-ms [0 0] - :end-of-today-ms [24 0] + (let [[hh mm ss ms] (case input + :start-of-today-ms [0 0 0 0] + :end-of-today-ms [23 59 59 999] (get-offset-hh-mm nil (subs (name input) 6)))] - (date-at-local-ms (t/today) hour minute 0 0))) + (date-at-local-ms (t/today) hh mm ss ms))) +;; relative-date returns a YYYMMDD string (defmethod resolve-keyword-input :relative-date [_ input _] (let [relative-to (get-relative-date input) [_ offset-direction offset offset-unit] (re-find #"^([+-])(\d+)([dwmy])$" (name input)) offset-date (get-offset-date relative-to offset-direction offset offset-unit)] (date->int offset-date))) +;; relative-date-time returns an epoch int (defmethod resolve-keyword-input :relative-date-time [_ input _] (let [relative-to (get-relative-date input) - [_ offset-direction offset offset-unit offset-time] (re-find #"^([+-])(\d+)([dwmy])-(ms|before|after|\d\d\d\d)$" (name input)) + [_ offset-direction offset offset-unit offset-time] (re-find #"^([+-])(\d+)([dwmy])-(ms|start|end|\d\d\d\d)$" (name input)) offset-date (get-offset-date relative-to offset-direction offset offset-unit) - [offset-hour offset-min] (get-offset-hh-mm offset-direction offset-time)] - (date-at-local-ms offset-date offset-hour offset-min 0 0))) + [hh mm ss ms] (get-offset-hh-mm offset-direction offset-time)] + (date-at-local-ms offset-date hh mm ss ms))) (defmethod resolve-keyword-input :DEPRECATED-relative-date [db input opts] ;; This handles all of the cases covered by the following: diff --git a/src/test/frontend/db/query_react_test.cljs b/src/test/frontend/db/query_react_test.cljs index 3dd83c8bec..24490d1bcf 100644 --- a/src/test/frontend/db/query_react_test.cljs +++ b/src/test/frontend/db/query_react_test.cljs @@ -91,22 +91,41 @@ adds rules that users often use" ;; These tests rely on seeding timestamps with properties. If this ability goes ;; away we could still test page-level timestamps (deftest resolve-input-for-timestamp-inputs - (let [today-timestamp (db-util/date-at-local-ms 0 0 0 0) - next-week-timestamp (db-util/date-at-local-ms (t/plus (t/today) (t/days 7)) - 0 0 0 0)] - (load-test-files [{:file/path "pages/page1.md" - :file/content (gstring/format "foo::bar -- yesterday + (load-test-files [{:file/path "pages/page1.md" + :file/content (gstring/format "foo::bar +- -1y +created-at:: %s +- -1m +created-at:: %s +- -1w +created-at:: %s +- -1d created-at:: %s - today created-at:: %s -- next week +- tonight +created-at:: %s +- +1d +created-at:: %s +- +1w +created-at:: %s +- +1m +created-at:: %s +- +1y created-at:: %s" - (dec today-timestamp) - (inc today-timestamp) - next-week-timestamp)}]) + (db-util/date-at-local-ms (t/minus (t/today) (t/years 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/minus (t/today) (t/months 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/minus (t/today) (t/weeks 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/minus (t/today) (t/days 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/today) 12 0 0 0) + (db-util/date-at-local-ms (t/today) 18 0 0 0) + (db-util/date-at-local-ms (t/plus (t/today) (t/days 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/plus (t/today) (t/weeks 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/plus (t/today) (t/months 1)) 0 0 0 0) + (db-util/date-at-local-ms (t/plus (t/today) (t/years 1)) 0 0 0 0))}]) - (is (= ["today"] + (is (= ["today" "tonight"] + (sort (map #(-> % :block/content string/split-lines first) (custom-query {:inputs [:-0d-ms :+0d-ms] :query '[:find (pull ?b [*]) @@ -115,10 +134,11 @@ created-at:: %s" [?b :block/content] [?b :block/created-at ?timestamp] [(>= ?timestamp ?start)] - [(<= ?timestamp ?end)]]}))) - ":+0d-ms and :-0d-ms resolve to correct datetime range") + [(<= ?timestamp ?end)]]})))) + ":+0d-ms and :-0d-ms resolve to correct datetime range") - (is (= ["yesterday" "today"] + (is (= ["+1d" "-1d" "today" "tonight"] + (sort (map #(-> % :block/content string/split-lines first) (custom-query {:inputs [:-1d-ms :+5d-ms] :query '[:find (pull ?b [*]) @@ -127,10 +147,50 @@ created-at:: %s" [?b :block/content] [?b :block/created-at ?timestamp] [(>= ?timestamp ?start)] - [(<= ?timestamp ?end)]]}))) - ":-Xd-ms and :+Xd-ms resolve to correct datetime range") + [(<= ?timestamp ?end)]]})))) + ":-Xd-ms and :+Xd-ms resolve to correct datetime range") - (is (= ["today"] + (is (= ["+1d" "+1w" "-1d" "-1w" "today" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:-1w-ms :+1w-ms] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":-Xw-ms and :+Xw-ms resolve to correct datetime range") + + (is (= ["+1d" "+1m" "+1w" "-1d" "-1m" "-1w" "today" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:-1m-ms :+1m-ms] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":-Xm-ms and :+Xm-ms resolve to correct datetime range") + + (is (= ["+1d" "+1m" "+1w" "+1y" "-1d" "-1m" "-1w" "-1y" "today" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:-1y-ms :+1y-ms] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":-Xy-ms and :+Xy-ms resolve to correct datetime range") + + (is (= ["today" "tonight"] + (sort (map #(-> % :block/content string/split-lines first) (custom-query {:inputs [:start-of-today-ms :end-of-today-ms] :query '[:find (pull ?b [*]) @@ -139,10 +199,11 @@ created-at:: %s" [?b :block/content] [?b :block/created-at ?timestamp] [(>= ?timestamp ?start)] - [(<= ?timestamp ?end)]]}))) - ":start-of-today-ms and :end-of-today-ms resolve to correct datetime range") + [(<= ?timestamp ?end)]]})))) + ":start-of-today-ms and :end-of-today-ms resolve to correct datetime range") - (is (= ["yesterday" "today"] + (is (= ["+1d" "-1d" "today" "tonight"] + (sort (map #(-> % :block/content string/split-lines first) (custom-query {:inputs [:1d-before-ms :5d-after-ms] :query '[:find (pull ?b [*]) @@ -151,8 +212,63 @@ created-at:: %s" [?b :block/content] [?b :block/created-at ?timestamp] [(>= ?timestamp ?start)] - [(<= ?timestamp ?end)]]}))) - ":Xd-before-ms and :Xd-after-ms resolve to correct datetime range"))) + [(<= ?timestamp ?end)]]})))) + ":Xd-before-ms and :Xd-after-ms resolve to correct datetime range") + + (is (= ["today" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:today-start :today-end] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":today-start and :today-end resolve to correct datetime range") + + (is (= ["+1d" "today" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:-0d-start :+1d-end] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":-XT-start and :+XT-end resolve to correct datetime range") + + (is (= ["today"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:today-1159 :today-1201] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":today-HHMM and :today-HHMM resolve to correct datetime range") + + (is (= ["+1d" "tonight"] + (sort + (map #(-> % :block/content string/split-lines first) + (custom-query {:inputs [:-0d-1201 :+1d-2359] + :query '[:find (pull ?b [*]) + :in $ ?start ?end + :where + [?b :block/content] + [?b :block/created-at ?timestamp] + [(>= ?timestamp ?start)] + [(<= ?timestamp ?end)]]})))) + ":-XT-HHMM and :+XT-HHMM resolve to correct datetime range")) + + + (deftest resolve-input-for-relative-date-queries (load-test-files [{:file/content "- -1y" :file/path "journals/2022_01_01.md"}