diff --git a/modules/drivers/redshift/src/metabase/driver/redshift.clj b/modules/drivers/redshift/src/metabase/driver/redshift.clj index e133555a9f77a4d064c6a2d98a3972a38cc7cd69..0f4c61137c83533e260a53d983854b9bd6fc33bb 100644 --- a/modules/drivers/redshift/src/metabase/driver/redshift.clj +++ b/modules/drivers/redshift/src/metabase/driver/redshift.clj @@ -222,19 +222,30 @@ :quarter (let [positive-diff (fn [a b] ; precondition: a <= b - (hx/cast - :integer - (hx/floor (hx// (hx/- (hsql/call :datediff (hsql/raw "month") a b) - (hx/cast :integer (hsql/call :> (extract :day a) (extract :day b)))) - 3))))] + (hx/cast :integer + (hx/floor + (hx// (hx/- (hsql/call :datediff (hsql/raw "month") a b) + (hx/cast :integer + ;; coalesce is needed because extract(day, a) > extract(day, b) + ;; returns null if a and b are equal + (hsql/call :coalesce + (hsql/call :> (extract :day a) (extract :day b)) + false))) + 3))))] (hsql/call :case (hsql/call :<= x y) (positive-diff x y) :else (hx/* -1 (positive-diff y x)))) :month - (let [positive-diff (fn [a b] ; precondition: a <= b - (hx/- - (hsql/call :datediff (hsql/raw "month") a b) - (hx/cast :integer (hsql/call :> (extract :day a) (extract :day b)))))] - (hsql/call :case (hsql/call :<= x y) (positive-diff x y) :else (hx/* -1 (positive-diff y x)))) + (let [positive-diff + (fn [a b] ; precondition: a <= b + (hx/- + (hsql/call :datediff (hsql/raw "month") a b) + (hx/cast :integer + ;; coalesce is needed because extract(day, a) > extract(day, b) + ;; returns null if a and b are equal + (hsql/call :coalesce + (hsql/call :> (extract :day a) (extract :day b)) + false))))] + (hsql/call :case (hsql/call :<= x y) (positive-diff x y) :else (hx/* -1 (positive-diff y x)))) :week (let [positive-diff (fn [a b] diff --git a/test/metabase/query_processor_test/date_time_zone_functions_test.clj b/test/metabase/query_processor_test/date_time_zone_functions_test.clj index 67c22b8c15af6aa59e9aa5d1e3bc73b601449fcf..c52587c1fa5cce56c156f4bbd26e090d77cc2c62 100644 --- a/test/metabase/query_processor_test/date_time_zone_functions_test.clj +++ b/test/metabase/query_processor_test/date_time_zone_functions_test.clj @@ -713,39 +713,47 @@ [:expression "diff-rev"]]}) (mt/formatted-rows [int int]) first))] - (doseq [[unit cases] [[:year [["2021-10-03T09:18:09" "2022-10-02T09:18:09" 0 "day under a year"] + (doseq [[unit cases] [[:year [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2021-10-03T09:18:09" "2022-10-02T09:18:09" 0 "day under a year"] ["2021-10-03T09:19:09" "2022-10-03T09:18:09" 1 "ignores time"] ["2016-02-03T09:19:09" "2017-02-02T09:19:09" 0 "starts in leap year before leap day"] ["2016-10-03T09:19:09" "2017-10-03T09:19:09" 1 "starts in leap year after leap day"] ["2017-06-10T08:30:00" "2019-07-10T08:30:00" 2 "multiple years"] ["2017-06-10" "2019-07-10" 2 "dates"]]] - [:quarter [["2021-10-03T09:18:09" "2022-01-02T09:18:09" 0 "day under a quarter"] + [:quarter [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2021-10-03T09:18:09" "2022-01-02T09:18:09" 0 "day under a quarter"] ["2021-10-03T09:19:09" "2022-01-03T09:18:09" 1 "ignores time"] ["2017-06-10T08:30:00" "2019-07-10T08:30:00" 8 "multiple years"] ["2017-06-10" "2019-07-10" 8 "dates"]]] - [:month [["2022-10-03T09:18:09" "2022-11-02T09:18:09" 0 "day under a month"] + [:month [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-03T09:18:09" "2022-11-02T09:18:09" 0 "day under a month"] ["2022-10-02T09:19:09" "2022-11-02T09:18:09" 1 "minute under a month"] ["2022-10-02T09:18:09" "2023-10-03T09:18:09" 12 "over a year"] ["2022-10-02" "2023-10-03" 12 "dates"]]] - [:week [["2022-10-01T09:18:09" "2022-10-04T09:18:09" 0 "under 7 days across week boundary"] - ["2022-10-02T09:19:09" "2022-10-09T09:18:09" 1 "ignores time"] + [:week [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-01T09:18:09" "2022-10-04T09:18:09" 0 "under 7 days across week boundary"] + ["2022-10-02T09:19:09" "2022-10-09T09:18:09" 1 "ignores time"] ["2022-10-02T09:18:09" "2023-10-03T09:18:09" 52 "over a year"] ["2022-10-02" "2023-10-03" 52 "dates"]]] - [:day [["2022-10-02T08:30:00" "2022-10-02T10:30:00" 0 "<24h same day"] + [:day [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-02T08:30:00" "2022-10-02T10:30:00" 0 "<24h same day"] ["2022-10-02T09:19:09" "2022-10-03T09:18:09" 1 "<24h consecutive days"] ["2021-10-02T08:30:00" "2022-10-05T10:30:00" 368 "over a year"] ["2021-10-02" "2022-10-05" 368 "dates"]]] - [:hour [["2022-10-02T08:30:00" "2022-10-02T08:34:00" 0 "minutes"] + [:hour [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-02T08:30:00" "2022-10-02T08:34:00" 0 "minutes"] ["2022-10-02T08:30:00" "2022-10-02T09:29:59.999" 0 "millisecond under an hour"] ["2022-10-02T08:30:00" "2022-10-05T08:34:00" 72 "hours"] ["2021-10-02T08:30:00" "2022-10-02T08:34:00" 8760 "over a year"] ["2021-10-02" "2022-10-02" 8760 "dates"]]] - [:minute [["2022-10-02T08:30:00" "2022-10-02T08:30:59.999" 0 "millisecond under a minute"] + [:minute [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-02T08:30:00" "2022-10-02T08:30:59.999" 0 "millisecond under a minute"] ["2022-10-02T08:30:00" "2022-10-02T08:34:00" 4 "minutes"] ["2022-10-02T08:30:00" "2022-10-02T10:30:00" 120 "hours"] ["2021-10-02T08:30:00" "2022-10-02T08:34:00" 525604 "over a year"] ["2021-10-02" "2022-10-02" 525600 "dates"]]] - [:second [["2022-10-02T08:30:00" "2022-10-02T08:30:00.999" 0 "millisecond under a second"] + [:second [["2021-10-03T09:00:00" "2021-10-03T09:00:00" 0 "same time"] + ["2022-10-02T08:30:00" "2022-10-02T08:30:00.999" 0 "millisecond under a second"] ["2022-10-02T08:30:00" "2022-10-02T08:34:00" 240 "minutes"] ["2022-10-02T08:30:00" "2022-10-02T10:30:00" 7200 "hours"] ["2021-10-02T08:30:00" "2022-10-02T08:34:00" 31536240 "over a year"]