Malli schema for temporal bucketing units and expressions.

(ns metabase.lib.schema.temporal-bucketing
  (:require
   [clojure.set :as set]
   [metabase.lib.schema.common :as common]
   [metabase.util.malli.registry :as mr]))

Units that you can EXTRACT from a date or datetime. These return integers in temporal bucketing expressions. The front end shows the options in this order.

(def ordered-date-extraction-units
  [:day-of-week
   :day-of-month
   :day-of-year
   :week-of-year
   :month-of-year
   :quarter-of-year
   :year
   :year-of-era])

Units that you can EXTRACT from a date or datetime. These return integers in temporal bucketing expressions.

(def date-extraction-units
  (set ordered-date-extraction-units))
(mr/def ::unit.date.extract
  (into [:enum {:error/message    "Valid date extraction unit"
                :decode/normalize common/normalize-keyword}]
        date-extraction-units))

Units that you can TRUNCATE a date or datetime to. In temporal bucketing expressions these return a :type/Date. The front end shows the options in this order.

(def ordered-date-truncation-units
  [:day :week :month :quarter :year])

Units that you can TRUNCATE a date or datetime to. In temporal bucketing expressions these return a :type/Date.

(def date-truncation-units
  (set ordered-date-truncation-units))
(mr/def ::unit.date.truncate
  (into [:enum {:error/message    "Valid date truncation unit"
                :decode/normalize common/normalize-keyword}]
        date-truncation-units))

Valid date or datetime bucketing units for either truncation or extraction operations. The front end shows the options in this order.

(def ordered-date-bucketing-units
  (into [] (distinct) (concat ordered-date-truncation-units ordered-date-extraction-units)))

Valid date or datetime bucketing units for either truncation or extraction operations.

(def date-bucketing-units
  (set ordered-date-bucketing-units))
(mr/def ::unit.date
  (into [:enum {:error/message    "Valid date bucketing unit"
                :decode/normalize common/normalize-keyword}]
        date-bucketing-units))

Units that you can EXTRACT from a time or datetime. These return integers in temporal bucketing expressions. The front end shows the options in this order.

(def ordered-time-extraction-units
  [:second-of-minute
   :minute-of-hour
   :hour-of-day])

Units that you can EXTRACT from a time or datetime. These return integers in temporal bucketing expressions.

(def time-extraction-units
  (set ordered-time-extraction-units))
(mr/def ::unit.time.extract
  (into [:enum {:error/message "Valid time extraction unit"}] time-extraction-units))

Units you can TRUNCATE a time or datetime to. These return the same type as the expression being bucketed in temporal bucketing expressions. The front end shows the options in this order.

(def ordered-time-truncation-units
  [:millisecond :second :minute :hour])

Units you can TRUNCATE a time or datetime to. These return the same type as the expression being bucketed in temporal bucketing expressions.

(def time-truncation-units
  (set ordered-time-truncation-units))
(mr/def ::unit.time.truncate
  (into [:enum {:error/message    "Valid time truncation unit"
                :decode/normalize common/normalize-keyword}]
        time-truncation-units))

Valid time bucketing units for either truncation or extraction operations. The front end shows the options in this order.

(def ordered-time-bucketing-units
  (into []
        (distinct)
        (concat ordered-time-truncation-units ordered-time-extraction-units)))

Valid time bucketing units for either truncation or extraction operations.

(def time-bucketing-units
  (set ordered-time-bucketing-units))
(mr/def ::unit.time
  (into [:enum {:error/message    "Valid time bucketing unit"
                :decode/normalize common/normalize-keyword}]
        time-bucketing-units))

Valid datetime bucketing units for truncation operations. The front end shows the options in this order.

(def ordered-datetime-truncation-units
  (into []
        (distinct)
        (concat ordered-time-truncation-units ordered-date-truncation-units)))

Valid datetime bucketing units for either truncation or extraction operations. The front end shows the options in this order.

(def ordered-datetime-bucketing-units
  (into []
        (distinct)
        (concat ordered-time-truncation-units ordered-date-truncation-units
                ordered-time-extraction-units ordered-date-extraction-units)))

Valid datetime bucketing units for either truncation or extraction operations.

(def datetime-bucketing-units
  (set ordered-datetime-bucketing-units))
(mr/def ::unit.date-time
  (into [:enum {:error/message    "Valid datetime bucketing unit"
                :decode/normalize common/normalize-keyword}]
        ordered-datetime-bucketing-units))

This is the same as [[datetime-bucketing-units]], but also includes :default.

(def temporal-bucketing-units
  (conj datetime-bucketing-units :default))
(mr/def ::unit
  (into [:enum {:error/message    "Valid temporal bucketing unit"
                :decode/normalize common/normalize-keyword}]
        temporal-bucketing-units))

Valid TRUNCATION units for a datetime.

(def datetime-truncation-units
  (set/union date-truncation-units time-truncation-units))
(mr/def ::unit.date-time.truncate
  (into [:enum {:error/message    "Valid datetime truncation unit"
                :decode/normalize common/normalize-keyword}]
        datetime-truncation-units))

Valid EXTRACTION units for a datetime. Extraction units return integers!

(def datetime-extraction-units
  (set/union date-extraction-units time-extraction-units))
(mr/def ::unit.date-time.extract
  (into [:enum {:error/message    "Valid datetime extraction unit"
                :decode/normalize common/normalize-keyword}]
        datetime-extraction-units))

Date units that are valid in intervals or clauses like :datetime-add. This is a superset of [[date-truncation-units]].

(def date-interval-units
  ;; it's the same but also includes `:year`, not normally allowed as a date truncation unit; `:year` is interpreted
  ;; as extraction instead.
  (conj date-truncation-units :year))
(mr/def ::unit.date.interval
  (into [:enum {:error/message    "Valid date interval unit"
                :decode/normalize common/normalize-keyword}]
        date-interval-units))

Time units that are valid in intervals or clauses like :datetime-add. Currently the same as [[time-truncation-units]].

(def time-interval-units
  time-truncation-units)
(mr/def ::unit.time.interval
  (into [:enum {:error/message    "Valid time interval unit"
                :decode/normalize common/normalize-keyword}]
        time-interval-units))

Units valid in intervals or clauses like :datetime-add for datetimes.

(def datetime-interval-units
  (set/union date-interval-units time-interval-units))
(mr/def ::unit.date-time.interval
  (into [:enum {:error/message    "Valid datetime interval unit"
                :decode/normalize common/normalize-keyword}]
        datetime-interval-units))
(mr/def ::option
  [:map
   [:lib/type [:= :option/temporal-bucketing]]
   [:unit ::unit]
   [:default {:optional true} :boolean]])