@qrvey/formula-lang 3.1.0-rc.908 → 3.2.0-rc.1078
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QRVEY-DATE-PRESETS.md +709 -0
- package/README.md +22 -0
- package/dist/cjs/constants/index.d.ts +5 -1
- package/dist/cjs/constants/index.js +4 -0
- package/dist/cjs/constants/index.js.map +1 -1
- package/dist/cjs/constants/interfaces.d.ts +38 -4
- package/dist/cjs/date-preset-tokens.d.ts +40 -0
- package/dist/cjs/date-preset-tokens.js +52 -0
- package/dist/cjs/date-preset-tokens.js.map +1 -0
- package/dist/cjs/date-presets.d.ts +65 -0
- package/dist/cjs/date-presets.js +319 -0
- package/dist/cjs/date-presets.js.map +1 -0
- package/dist/cjs/errors/analyzer/clickhouse.d.ts +8 -0
- package/dist/cjs/errors/analyzer/clickhouse.js +31 -0
- package/dist/cjs/errors/analyzer/clickhouse.js.map +1 -0
- package/dist/cjs/errors/analyzer/index.js +6 -1
- package/dist/cjs/errors/analyzer/index.js.map +1 -1
- package/dist/cjs/functions/abs.js +4 -0
- package/dist/cjs/functions/abs.js.map +1 -1
- package/dist/cjs/functions/aggAvg.js +6 -0
- package/dist/cjs/functions/aggAvg.js.map +1 -1
- package/dist/cjs/functions/aggCount.js +6 -0
- package/dist/cjs/functions/aggCount.js.map +1 -1
- package/dist/cjs/functions/aggDistcount.js +6 -0
- package/dist/cjs/functions/aggDistcount.js.map +1 -1
- package/dist/cjs/functions/aggMax.js +4 -0
- package/dist/cjs/functions/aggMax.js.map +1 -1
- package/dist/cjs/functions/aggMed.js +5 -0
- package/dist/cjs/functions/aggMed.js.map +1 -1
- package/dist/cjs/functions/aggMin.js +4 -0
- package/dist/cjs/functions/aggMin.js.map +1 -1
- package/dist/cjs/functions/aggSum.js +5 -0
- package/dist/cjs/functions/aggSum.js.map +1 -1
- package/dist/cjs/functions/and.js +4 -0
- package/dist/cjs/functions/and.js.map +1 -1
- package/dist/cjs/functions/calendarPeriod.d.ts +2 -0
- package/dist/cjs/functions/calendarPeriod.js +46 -0
- package/dist/cjs/functions/calendarPeriod.js.map +1 -0
- package/dist/cjs/functions/concatenate.js +4 -0
- package/dist/cjs/functions/concatenate.js.map +1 -1
- package/dist/cjs/functions/date.d.ts +2 -0
- package/dist/cjs/functions/date.js +27 -0
- package/dist/cjs/functions/date.js.map +1 -0
- package/dist/cjs/functions/datePresetUtils.d.ts +31 -0
- package/dist/cjs/functions/datePresetUtils.js +621 -0
- package/dist/cjs/functions/datePresetUtils.js.map +1 -0
- package/dist/cjs/functions/dateRange.d.ts +2 -0
- package/dist/cjs/functions/dateRange.js +38 -0
- package/dist/cjs/functions/dateRange.js.map +1 -0
- package/dist/cjs/functions/dateadd.js +21 -0
- package/dist/cjs/functions/dateadd.js.map +1 -1
- package/dist/cjs/functions/datedif.js +6 -0
- package/dist/cjs/functions/datedif.js.map +1 -1
- package/dist/cjs/functions/datesubtract.js +21 -0
- package/dist/cjs/functions/datesubtract.js.map +1 -1
- package/dist/cjs/functions/day.js +4 -0
- package/dist/cjs/functions/day.js.map +1 -1
- package/dist/cjs/functions/dayofweek.js +14 -0
- package/dist/cjs/functions/dayofweek.js.map +1 -1
- package/dist/cjs/functions/endOf.d.ts +2 -0
- package/dist/cjs/functions/endOf.js +26 -0
- package/dist/cjs/functions/endOf.js.map +1 -0
- package/dist/cjs/functions/even.js +4 -0
- package/dist/cjs/functions/even.js.map +1 -1
- package/dist/cjs/functions/exp.js +4 -0
- package/dist/cjs/functions/exp.js.map +1 -1
- package/dist/cjs/functions/hour.js +12 -0
- package/dist/cjs/functions/hour.js.map +1 -1
- package/dist/cjs/functions/if.js +4 -0
- package/dist/cjs/functions/if.js.map +1 -1
- package/dist/cjs/functions/ifs.js +4 -0
- package/dist/cjs/functions/ifs.js.map +1 -1
- package/dist/cjs/functions/include.js +4 -0
- package/dist/cjs/functions/include.js.map +1 -1
- package/dist/cjs/functions/index.js +40 -4
- package/dist/cjs/functions/index.js.map +1 -1
- package/dist/cjs/functions/isNull.js +4 -0
- package/dist/cjs/functions/isNull.js.map +1 -1
- package/dist/cjs/functions/left.js +10 -0
- package/dist/cjs/functions/left.js.map +1 -1
- package/dist/cjs/functions/length.js +8 -0
- package/dist/cjs/functions/length.js.map +1 -1
- package/dist/cjs/functions/log.js +10 -0
- package/dist/cjs/functions/log.js.map +1 -1
- package/dist/cjs/functions/lower.js +5 -0
- package/dist/cjs/functions/lower.js.map +1 -1
- package/dist/cjs/functions/max.js +4 -0
- package/dist/cjs/functions/max.js.map +1 -1
- package/dist/cjs/functions/mid.js +16 -0
- package/dist/cjs/functions/mid.js.map +1 -1
- package/dist/cjs/functions/millisecond.js +8 -0
- package/dist/cjs/functions/millisecond.js.map +1 -1
- package/dist/cjs/functions/min.js +4 -0
- package/dist/cjs/functions/min.js.map +1 -1
- package/dist/cjs/functions/minute.js +4 -0
- package/dist/cjs/functions/minute.js.map +1 -1
- package/dist/cjs/functions/month.js +4 -0
- package/dist/cjs/functions/month.js.map +1 -1
- package/dist/cjs/functions/now.js +8 -0
- package/dist/cjs/functions/now.js.map +1 -1
- package/dist/cjs/functions/odd.js +4 -0
- package/dist/cjs/functions/odd.js.map +1 -1
- package/dist/cjs/functions/or.js +4 -0
- package/dist/cjs/functions/or.js.map +1 -1
- package/dist/cjs/functions/part.d.ts +2 -0
- package/dist/cjs/functions/part.js +52 -0
- package/dist/cjs/functions/part.js.map +1 -0
- package/dist/cjs/functions/partialDate.d.ts +2 -0
- package/dist/cjs/functions/partialDate.js +56 -0
- package/dist/cjs/functions/partialDate.js.map +1 -0
- package/dist/cjs/functions/periodAt.d.ts +2 -0
- package/dist/cjs/functions/periodAt.js +61 -0
- package/dist/cjs/functions/periodAt.js.map +1 -0
- package/dist/cjs/functions/power.js +4 -0
- package/dist/cjs/functions/power.js.map +1 -1
- package/dist/cjs/functions/proper.js +4 -0
- package/dist/cjs/functions/proper.js.map +1 -1
- package/dist/cjs/functions/random.js +4 -0
- package/dist/cjs/functions/random.js.map +1 -1
- package/dist/cjs/functions/relativePeriod.d.ts +2 -0
- package/dist/cjs/functions/relativePeriod.js +52 -0
- package/dist/cjs/functions/relativePeriod.js.map +1 -0
- package/dist/cjs/functions/replace.js +4 -0
- package/dist/cjs/functions/replace.js.map +1 -1
- package/dist/cjs/functions/right.js +10 -0
- package/dist/cjs/functions/right.js.map +1 -1
- package/dist/cjs/functions/round.js +17 -0
- package/dist/cjs/functions/round.js.map +1 -1
- package/dist/cjs/functions/rounddown.js +9 -0
- package/dist/cjs/functions/rounddown.js.map +1 -1
- package/dist/cjs/functions/roundup.js +9 -0
- package/dist/cjs/functions/roundup.js.map +1 -1
- package/dist/cjs/functions/second.js +4 -0
- package/dist/cjs/functions/second.js.map +1 -1
- package/dist/cjs/functions/sqrt.js +4 -0
- package/dist/cjs/functions/sqrt.js.map +1 -1
- package/dist/cjs/functions/startOf.d.ts +2 -0
- package/dist/cjs/functions/startOf.js +26 -0
- package/dist/cjs/functions/startOf.js.map +1 -0
- package/dist/cjs/functions/text.js +4 -0
- package/dist/cjs/functions/text.js.map +1 -1
- package/dist/cjs/functions/today.d.ts +2 -0
- package/dist/cjs/functions/today.js +20 -0
- package/dist/cjs/functions/today.js.map +1 -0
- package/dist/cjs/functions/totalAvg.js +6 -0
- package/dist/cjs/functions/totalAvg.js.map +1 -1
- package/dist/cjs/functions/totalCount.js +6 -0
- package/dist/cjs/functions/totalCount.js.map +1 -1
- package/dist/cjs/functions/totalDistcount.js +6 -0
- package/dist/cjs/functions/totalDistcount.js.map +1 -1
- package/dist/cjs/functions/totalMax.js +4 -0
- package/dist/cjs/functions/totalMax.js.map +1 -1
- package/dist/cjs/functions/totalMed.js +5 -0
- package/dist/cjs/functions/totalMed.js.map +1 -1
- package/dist/cjs/functions/totalMin.js +4 -0
- package/dist/cjs/functions/totalMin.js.map +1 -1
- package/dist/cjs/functions/totalSum.js +4 -0
- package/dist/cjs/functions/totalSum.js.map +1 -1
- package/dist/cjs/functions/trim.js +4 -0
- package/dist/cjs/functions/trim.js.map +1 -1
- package/dist/cjs/functions/upper.js +5 -0
- package/dist/cjs/functions/upper.js.map +1 -1
- package/dist/cjs/functions/year.js +4 -0
- package/dist/cjs/functions/year.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/parser/engine-validators/index.js +1 -0
- package/dist/cjs/parser/engine-validators/index.js.map +1 -1
- package/dist/cjs/parser/json-parser.js +2 -0
- package/dist/cjs/parser/json-parser.js.map +1 -1
- package/dist/cjs/transpiler/columnTranspilation.js +13 -1
- package/dist/cjs/transpiler/columnTranspilation.js.map +1 -1
- package/dist/cjs/transpiler/index.d.ts +1 -0
- package/dist/cjs/transpiler/index.js +19 -3
- package/dist/cjs/transpiler/index.js.map +1 -1
- package/dist/cjs/utils/addDecimalPointIfNeeded.js +1 -0
- package/dist/cjs/utils/addDecimalPointIfNeeded.js.map +1 -1
- package/dist/cjs/utils/clickhouse/index.d.ts +1 -0
- package/dist/cjs/utils/clickhouse/index.js +8 -0
- package/dist/cjs/utils/clickhouse/index.js.map +1 -0
- package/dist/cjs/utils/clickhouse/scripts.d.ts +4 -0
- package/dist/cjs/utils/clickhouse/scripts.js +49 -0
- package/dist/cjs/utils/clickhouse/scripts.js.map +1 -0
- package/dist/cjs/utils/customFunctions.d.ts +1 -0
- package/dist/cjs/utils/customFunctions.js +15 -1
- package/dist/cjs/utils/customFunctions.js.map +1 -1
- package/dist/cjs/utils/isALiteral.js +11 -1
- package/dist/cjs/utils/isALiteral.js.map +1 -1
- package/dist/module/constants/index.d.ts +5 -1
- package/dist/module/constants/index.js +4 -0
- package/dist/module/constants/index.js.map +1 -1
- package/dist/module/constants/interfaces.d.ts +38 -4
- package/dist/module/date-preset-tokens.d.ts +40 -0
- package/dist/module/date-preset-tokens.js +48 -0
- package/dist/module/date-preset-tokens.js.map +1 -0
- package/dist/module/date-presets.d.ts +65 -0
- package/dist/module/date-presets.js +313 -0
- package/dist/module/date-presets.js.map +1 -0
- package/dist/module/errors/analyzer/clickhouse.d.ts +8 -0
- package/dist/module/errors/analyzer/clickhouse.js +27 -0
- package/dist/module/errors/analyzer/clickhouse.js.map +1 -0
- package/dist/module/errors/analyzer/index.js +6 -1
- package/dist/module/errors/analyzer/index.js.map +1 -1
- package/dist/module/functions/abs.js +4 -0
- package/dist/module/functions/abs.js.map +1 -1
- package/dist/module/functions/aggAvg.js +6 -0
- package/dist/module/functions/aggAvg.js.map +1 -1
- package/dist/module/functions/aggCount.js +6 -0
- package/dist/module/functions/aggCount.js.map +1 -1
- package/dist/module/functions/aggDistcount.js +6 -0
- package/dist/module/functions/aggDistcount.js.map +1 -1
- package/dist/module/functions/aggMax.js +4 -0
- package/dist/module/functions/aggMax.js.map +1 -1
- package/dist/module/functions/aggMed.js +5 -0
- package/dist/module/functions/aggMed.js.map +1 -1
- package/dist/module/functions/aggMin.js +4 -0
- package/dist/module/functions/aggMin.js.map +1 -1
- package/dist/module/functions/aggSum.js +5 -0
- package/dist/module/functions/aggSum.js.map +1 -1
- package/dist/module/functions/and.js +4 -0
- package/dist/module/functions/and.js.map +1 -1
- package/dist/module/functions/calendarPeriod.d.ts +2 -0
- package/dist/module/functions/calendarPeriod.js +43 -0
- package/dist/module/functions/calendarPeriod.js.map +1 -0
- package/dist/module/functions/concatenate.js +4 -0
- package/dist/module/functions/concatenate.js.map +1 -1
- package/dist/module/functions/date.d.ts +2 -0
- package/dist/module/functions/date.js +24 -0
- package/dist/module/functions/date.js.map +1 -0
- package/dist/module/functions/datePresetUtils.d.ts +31 -0
- package/dist/module/functions/datePresetUtils.js +601 -0
- package/dist/module/functions/datePresetUtils.js.map +1 -0
- package/dist/module/functions/dateRange.d.ts +2 -0
- package/dist/module/functions/dateRange.js +35 -0
- package/dist/module/functions/dateRange.js.map +1 -0
- package/dist/module/functions/dateadd.js +21 -0
- package/dist/module/functions/dateadd.js.map +1 -1
- package/dist/module/functions/datedif.js +6 -0
- package/dist/module/functions/datedif.js.map +1 -1
- package/dist/module/functions/datesubtract.js +21 -0
- package/dist/module/functions/datesubtract.js.map +1 -1
- package/dist/module/functions/day.js +4 -0
- package/dist/module/functions/day.js.map +1 -1
- package/dist/module/functions/dayofweek.js +14 -0
- package/dist/module/functions/dayofweek.js.map +1 -1
- package/dist/module/functions/endOf.d.ts +2 -0
- package/dist/module/functions/endOf.js +23 -0
- package/dist/module/functions/endOf.js.map +1 -0
- package/dist/module/functions/even.js +4 -0
- package/dist/module/functions/even.js.map +1 -1
- package/dist/module/functions/exp.js +4 -0
- package/dist/module/functions/exp.js.map +1 -1
- package/dist/module/functions/hour.js +12 -0
- package/dist/module/functions/hour.js.map +1 -1
- package/dist/module/functions/if.js +4 -0
- package/dist/module/functions/if.js.map +1 -1
- package/dist/module/functions/ifs.js +4 -0
- package/dist/module/functions/ifs.js.map +1 -1
- package/dist/module/functions/include.js +4 -0
- package/dist/module/functions/include.js.map +1 -1
- package/dist/module/functions/index.js +40 -4
- package/dist/module/functions/index.js.map +1 -1
- package/dist/module/functions/isNull.js +4 -0
- package/dist/module/functions/isNull.js.map +1 -1
- package/dist/module/functions/left.js +10 -0
- package/dist/module/functions/left.js.map +1 -1
- package/dist/module/functions/length.js +8 -0
- package/dist/module/functions/length.js.map +1 -1
- package/dist/module/functions/log.js +10 -0
- package/dist/module/functions/log.js.map +1 -1
- package/dist/module/functions/lower.js +5 -0
- package/dist/module/functions/lower.js.map +1 -1
- package/dist/module/functions/max.js +4 -0
- package/dist/module/functions/max.js.map +1 -1
- package/dist/module/functions/mid.js +16 -0
- package/dist/module/functions/mid.js.map +1 -1
- package/dist/module/functions/millisecond.js +8 -0
- package/dist/module/functions/millisecond.js.map +1 -1
- package/dist/module/functions/min.js +4 -0
- package/dist/module/functions/min.js.map +1 -1
- package/dist/module/functions/minute.js +4 -0
- package/dist/module/functions/minute.js.map +1 -1
- package/dist/module/functions/month.js +4 -0
- package/dist/module/functions/month.js.map +1 -1
- package/dist/module/functions/now.js +8 -0
- package/dist/module/functions/now.js.map +1 -1
- package/dist/module/functions/odd.js +4 -0
- package/dist/module/functions/odd.js.map +1 -1
- package/dist/module/functions/or.js +4 -0
- package/dist/module/functions/or.js.map +1 -1
- package/dist/module/functions/part.d.ts +2 -0
- package/dist/module/functions/part.js +49 -0
- package/dist/module/functions/part.js.map +1 -0
- package/dist/module/functions/partialDate.d.ts +2 -0
- package/dist/module/functions/partialDate.js +53 -0
- package/dist/module/functions/partialDate.js.map +1 -0
- package/dist/module/functions/periodAt.d.ts +2 -0
- package/dist/module/functions/periodAt.js +58 -0
- package/dist/module/functions/periodAt.js.map +1 -0
- package/dist/module/functions/power.js +4 -0
- package/dist/module/functions/power.js.map +1 -1
- package/dist/module/functions/proper.js +4 -0
- package/dist/module/functions/proper.js.map +1 -1
- package/dist/module/functions/random.js +4 -0
- package/dist/module/functions/random.js.map +1 -1
- package/dist/module/functions/relativePeriod.d.ts +2 -0
- package/dist/module/functions/relativePeriod.js +49 -0
- package/dist/module/functions/relativePeriod.js.map +1 -0
- package/dist/module/functions/replace.js +4 -0
- package/dist/module/functions/replace.js.map +1 -1
- package/dist/module/functions/right.js +10 -0
- package/dist/module/functions/right.js.map +1 -1
- package/dist/module/functions/round.js +17 -0
- package/dist/module/functions/round.js.map +1 -1
- package/dist/module/functions/rounddown.js +9 -0
- package/dist/module/functions/rounddown.js.map +1 -1
- package/dist/module/functions/roundup.js +9 -0
- package/dist/module/functions/roundup.js.map +1 -1
- package/dist/module/functions/second.js +4 -0
- package/dist/module/functions/second.js.map +1 -1
- package/dist/module/functions/sqrt.js +4 -0
- package/dist/module/functions/sqrt.js.map +1 -1
- package/dist/module/functions/startOf.d.ts +2 -0
- package/dist/module/functions/startOf.js +23 -0
- package/dist/module/functions/startOf.js.map +1 -0
- package/dist/module/functions/text.js +4 -0
- package/dist/module/functions/text.js.map +1 -1
- package/dist/module/functions/today.d.ts +2 -0
- package/dist/module/functions/today.js +17 -0
- package/dist/module/functions/today.js.map +1 -0
- package/dist/module/functions/totalAvg.js +6 -0
- package/dist/module/functions/totalAvg.js.map +1 -1
- package/dist/module/functions/totalCount.js +6 -0
- package/dist/module/functions/totalCount.js.map +1 -1
- package/dist/module/functions/totalDistcount.js +6 -0
- package/dist/module/functions/totalDistcount.js.map +1 -1
- package/dist/module/functions/totalMax.js +4 -0
- package/dist/module/functions/totalMax.js.map +1 -1
- package/dist/module/functions/totalMed.js +5 -0
- package/dist/module/functions/totalMed.js.map +1 -1
- package/dist/module/functions/totalMin.js +4 -0
- package/dist/module/functions/totalMin.js.map +1 -1
- package/dist/module/functions/totalSum.js +4 -0
- package/dist/module/functions/totalSum.js.map +1 -1
- package/dist/module/functions/trim.js +4 -0
- package/dist/module/functions/trim.js.map +1 -1
- package/dist/module/functions/upper.js +5 -0
- package/dist/module/functions/upper.js.map +1 -1
- package/dist/module/functions/year.js +4 -0
- package/dist/module/functions/year.js.map +1 -1
- package/dist/module/index.d.ts +3 -1
- package/dist/module/index.js +2 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/parser/engine-validators/index.js +1 -0
- package/dist/module/parser/engine-validators/index.js.map +1 -1
- package/dist/module/parser/json-parser.js +2 -0
- package/dist/module/parser/json-parser.js.map +1 -1
- package/dist/module/transpiler/columnTranspilation.js +13 -1
- package/dist/module/transpiler/columnTranspilation.js.map +1 -1
- package/dist/module/transpiler/index.d.ts +1 -0
- package/dist/module/transpiler/index.js +20 -4
- package/dist/module/transpiler/index.js.map +1 -1
- package/dist/module/utils/addDecimalPointIfNeeded.js +1 -0
- package/dist/module/utils/addDecimalPointIfNeeded.js.map +1 -1
- package/dist/module/utils/clickhouse/index.d.ts +1 -0
- package/dist/module/utils/clickhouse/index.js +2 -0
- package/dist/module/utils/clickhouse/index.js.map +1 -0
- package/dist/module/utils/clickhouse/scripts.d.ts +4 -0
- package/dist/module/utils/clickhouse/scripts.js +43 -0
- package/dist/module/utils/clickhouse/scripts.js.map +1 -0
- package/dist/module/utils/customFunctions.d.ts +1 -0
- package/dist/module/utils/customFunctions.js +13 -0
- package/dist/module/utils/customFunctions.js.map +1 -1
- package/dist/module/utils/isALiteral.js +12 -2
- package/dist/module/utils/isALiteral.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
# QDP Date Presets
|
|
2
|
+
|
|
3
|
+
This document summarizes the current state of QDP Date Presets in Formula Lang: public API, output types, available functions, supported JSON, legacy tokens, calendar rules, and equivalences with the external date picker.
|
|
4
|
+
|
|
5
|
+
The reference date used in this document's examples is `2026-07-22`, unless an example states otherwise. The QDP engine resolves dynamic values at execution time.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
QDP Date Presets makes it possible to express date values produced by operators, legacy tokens, or external components such as the date picker. The output is resolved through Formula Lang, but restricted to the `QDP` engine and date-like result types.
|
|
10
|
+
|
|
11
|
+
The API does not change the main grammar. It uses regular Formula Lang functions registered for `ENGINES.QDP`.
|
|
12
|
+
|
|
13
|
+
## Public API
|
|
14
|
+
|
|
15
|
+
The main APIs are in `src/date-presets.ts` and are exported from `src/index.ts`.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
TranspileDatePreset(program: string, context?: FormulaContext): DatePresetTranspilationResponse | undefined
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Compiles a QDP expression and returns a typed result. Only expressions whose final result is `date`, `dateRange`, or `partialDate` are valid.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
TranspileJSONToDatePreset(input: DatePresetJSON | string): string
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Converts a legacy token or date preset JSON object into a QDP expression.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
FormatDatePreset(value: DatePresetValue, options?: DatePresetFormatOptions): DatePresetValue
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Formats dates, ranges, and partial dates for UI.
|
|
34
|
+
|
|
35
|
+
## Output Types
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
type DatePresetValue = string | DateRangeValue | PartialDateValue;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`date` is represented as an ISO string:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
"2026-07-22T00:00:00.000Z"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`dateRange` is represented as an object with `start` and `end`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"start": "2026-07-01T00:00:00.000Z",
|
|
52
|
+
"end": "2026-07-31T23:59:59.999Z"
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`partialDate` represents incomplete or recurring dates:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"month": 4,
|
|
61
|
+
"day": 15
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Supported fields for `partialDate`:
|
|
66
|
+
|
|
67
|
+
| Field | Meaning | Range |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `year` | Specific year | Integer |
|
|
70
|
+
| `month` | Month | 1-12 |
|
|
71
|
+
| `quarter` | Quarter | 1-4 |
|
|
72
|
+
| `week` | Week | 1-54 |
|
|
73
|
+
| `day` | Day of month | 1-31 |
|
|
74
|
+
|
|
75
|
+
## Value Types
|
|
76
|
+
|
|
77
|
+
`TranspileDatePreset` returns `valueType` to describe the nature of the value.
|
|
78
|
+
|
|
79
|
+
| Value type | Meaning | Examples |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `fixed` | Fixed value or materialized range | `DATE("2026-07-20")`, `DATE_RANGE(...)` |
|
|
82
|
+
| `recurring` | Partial pattern that repeats | `PARTIAL_DATE("ANY", 4)`, `PARTIAL_DATE("ANY", 4, "ANY", "ANY", 15)` |
|
|
83
|
+
| `relative` | Period relative to the calendar or positioned inside a period | `CALENDAR_PERIOD("MONTH", 0)`, `PERIOD_AT("MONTH", 4, 2026)` |
|
|
84
|
+
| `rolling` | Moving window from an anchor | `RELATIVE_PERIOD(-29, "DAY")` |
|
|
85
|
+
|
|
86
|
+
Current note: `PERIOD_AT("MONTH", 4, 2026)` produces a concrete range, but it is classified as `relative` because the root expression is `PERIOD_AT`. If the business goal requires distinguishing `April 2026` as `fixed`, that would be a classification improvement, not a resolution change.
|
|
87
|
+
|
|
88
|
+
## Resolution Context
|
|
89
|
+
|
|
90
|
+
QDP functions can receive `FormulaContext` with date preset configuration:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
{
|
|
94
|
+
datePreset: {
|
|
95
|
+
calendar: 'gregorian',
|
|
96
|
+
timezone: 'UTC',
|
|
97
|
+
locale: 'en-US',
|
|
98
|
+
fiscalYearStartMonth: 1,
|
|
99
|
+
fiscalYearStartDay: 1,
|
|
100
|
+
weekStartsOn: 0
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Current defaults:
|
|
106
|
+
|
|
107
|
+
| Option | Default | Notes |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `calendar` | `gregorian` | Also supports `corporate-fiscal`, `retail-4-4-5`, `retail-4-5-4` |
|
|
110
|
+
| `timezone` | `UTC` | Affects day starts/ends and periods |
|
|
111
|
+
| `locale` | `en-US` | Used by formatting options |
|
|
112
|
+
| `fiscalYearStartMonth` | `1` | Clamped to 1-12 |
|
|
113
|
+
| `fiscalYearStartDay` | `1` | Clamped to 1-31 and adjusted to the last valid day of the month |
|
|
114
|
+
| `weekStartsOn` | `0` | Sunday. Accepts 0-6 or English weekday names |
|
|
115
|
+
|
|
116
|
+
Current week convention:
|
|
117
|
+
|
|
118
|
+
- The default is Sunday (`weekStartsOn: 0`).
|
|
119
|
+
- Week 1 of a year starts on the Sunday on or before Jan 1.
|
|
120
|
+
- Some years can have W54 under this convention.
|
|
121
|
+
- `PERIOD_AT("WEEK", "LAST", year)` is preferred for representing the last week of the year because it avoids hardcoding 52, 53, or 54.
|
|
122
|
+
|
|
123
|
+
## QDP Date Preset Functions
|
|
124
|
+
|
|
125
|
+
### `NOW()`
|
|
126
|
+
|
|
127
|
+
Returns the current timestamp.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
NOW()
|
|
131
|
+
// 2026-07-22T23:42:50.413Z
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Output: `date`.
|
|
135
|
+
|
|
136
|
+
Value type when used as the final result: `fixed`.
|
|
137
|
+
|
|
138
|
+
### `TODAY()`
|
|
139
|
+
|
|
140
|
+
Returns the start of the current day in the context timezone.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
TODAY()
|
|
144
|
+
// 2026-07-22T00:00:00.000Z
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Output: `date`.
|
|
148
|
+
|
|
149
|
+
Value type when used as the final result: `fixed`.
|
|
150
|
+
|
|
151
|
+
### `DATE(value)`
|
|
152
|
+
|
|
153
|
+
Normalizes an ISO date or ISO date-time string to UTC ISO.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
DATE("2026-07-20")
|
|
157
|
+
// 2026-07-20T00:00:00.000Z
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Supported input formats:
|
|
161
|
+
|
|
162
|
+
| Input | Example | Resolved value |
|
|
163
|
+
| --- | --- | --- |
|
|
164
|
+
| ISO date | `DATE("2026-07-08")` | `2026-07-08T00:00:00.000Z` |
|
|
165
|
+
| ISO date-time without timezone | `DATE("2026-07-08T15:30")` | `2026-07-08T15:30:00.000Z` |
|
|
166
|
+
| ISO date-time with UTC timezone | `DATE("2026-07-08T15:30:45Z")` | `2026-07-08T15:30:45.000Z` |
|
|
167
|
+
| ISO date-time with offset timezone | `DATE("2026-07-08T15:30:45-05:00")` | `2026-07-08T20:30:45.000Z` |
|
|
168
|
+
|
|
169
|
+
Parameters:
|
|
170
|
+
|
|
171
|
+
| Parameter | Type | Required | Validation |
|
|
172
|
+
| --- | --- | --- | --- |
|
|
173
|
+
| `VALUE` | `string` | Yes | ISO date or ISO date-time |
|
|
174
|
+
|
|
175
|
+
Rules:
|
|
176
|
+
|
|
177
|
+
- `DATE("2026-07-08")` is valid and resolves to `2026-07-08T00:00:00.000Z`.
|
|
178
|
+
- Calendrically invalid dates, such as `DATE("2026-02-31T00:00")`, are rejected.
|
|
179
|
+
- If the string does not include a timezone, UTC is assumed.
|
|
180
|
+
|
|
181
|
+
Output: `date`.
|
|
182
|
+
|
|
183
|
+
Value type: `fixed`.
|
|
184
|
+
|
|
185
|
+
### `DATE_RANGE(start, end)`
|
|
186
|
+
|
|
187
|
+
Builds a range between two dates.
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
DATE_RANGE(
|
|
191
|
+
DATE("2026-07-20"),
|
|
192
|
+
END_OF(DATE("2026-07-25"))
|
|
193
|
+
)
|
|
194
|
+
// { start: "2026-07-20T00:00:00.000Z", end: "2026-07-25T23:59:59.999Z" }
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Parameters:
|
|
198
|
+
|
|
199
|
+
| Parameter | Type | Required |
|
|
200
|
+
| --- | --- | --- |
|
|
201
|
+
| `START` | `date` | Yes |
|
|
202
|
+
| `END` | `date` | Yes |
|
|
203
|
+
|
|
204
|
+
Rules:
|
|
205
|
+
|
|
206
|
+
- `END` must be greater than or equal to `START`.
|
|
207
|
+
- If `END < START`, the function returns `INVALID_DATE_RANGE`.
|
|
208
|
+
|
|
209
|
+
Output: `dateRange`.
|
|
210
|
+
|
|
211
|
+
Value type: `fixed`.
|
|
212
|
+
|
|
213
|
+
### `RELATIVE_PERIOD(offset, unit, anchor?)`
|
|
214
|
+
|
|
215
|
+
Creates a moving window relative to an anchor. If no anchor is passed, it uses `TODAY()`.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
RELATIVE_PERIOD(-29, "DAY")
|
|
219
|
+
// { start: "2026-06-23T00:00:00.000Z", end: "2026-07-22T23:59:59.999Z" }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Parameters:
|
|
223
|
+
|
|
224
|
+
| Parameter | Type | Required | Values |
|
|
225
|
+
| --- | --- | --- | --- |
|
|
226
|
+
| `OFFSET` | Integer `number` | Yes | Negative, zero, or positive |
|
|
227
|
+
| `UNIT` | `string` | Yes | `DAY`, `WEEK`, `MONTH`, `QUARTER`, `YEAR` |
|
|
228
|
+
| `ANCHOR` | `date` | No | Base date |
|
|
229
|
+
|
|
230
|
+
Semantics:
|
|
231
|
+
|
|
232
|
+
- Negative offset: from `anchor + offset` to the end of the anchor day.
|
|
233
|
+
- Positive offset: from the start of the anchor day to `anchor + offset`.
|
|
234
|
+
- It is rolling and not necessarily aligned to calendar boundaries.
|
|
235
|
+
|
|
236
|
+
Examples:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
RELATIVE_PERIOD(-2, "WEEK", DATE("2026-07-08T15:30"))
|
|
240
|
+
// 2026-06-24T00:00:00.000Z -> 2026-07-08T23:59:59.999Z
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Output: `dateRange`.
|
|
244
|
+
|
|
245
|
+
Value type: `rolling`.
|
|
246
|
+
|
|
247
|
+
### `CALENDAR_PERIOD(period, offset?)`
|
|
248
|
+
|
|
249
|
+
Returns a complete calendar period containing the current day, shifted by `offset`.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
CALENDAR_PERIOD("MONTH", 0)
|
|
253
|
+
// 2026-07-01T00:00:00.000Z -> 2026-07-31T23:59:59.999Z
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Parameters:
|
|
257
|
+
|
|
258
|
+
| Parameter | Type | Required | Values |
|
|
259
|
+
| --- | --- | --- | --- |
|
|
260
|
+
| `PERIOD` | `string` | Yes | `DAY`, `WEEK`, `MONTH`, `QUARTER`, `YEAR` |
|
|
261
|
+
| `OFFSET` | Integer `number` | No | Default `0` |
|
|
262
|
+
|
|
263
|
+
Semantics:
|
|
264
|
+
|
|
265
|
+
- `0` means the current period.
|
|
266
|
+
- `-1` means the previous period.
|
|
267
|
+
- `1` means the next period.
|
|
268
|
+
- Respects calendar boundaries, timezone, fiscal calendar, and week start from the context.
|
|
269
|
+
|
|
270
|
+
Examples:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
CALENDAR_PERIOD("WEEK", 0)
|
|
274
|
+
// with weekStartsOn Sunday: 2026-07-19T00:00:00.000Z -> 2026-07-25T23:59:59.999Z
|
|
275
|
+
|
|
276
|
+
CALENDAR_PERIOD("QUARTER", -1)
|
|
277
|
+
// 2026-04-01T00:00:00.000Z -> 2026-06-30T23:59:59.999Z
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Output: `dateRange`.
|
|
281
|
+
|
|
282
|
+
Value type: `relative`.
|
|
283
|
+
|
|
284
|
+
### `PERIOD_AT(period, position, year?)`
|
|
285
|
+
|
|
286
|
+
Returns the period located at a position inside a year. If `year` is not passed, it uses the current year from the context.
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
PERIOD_AT("MONTH", 4, 2026)
|
|
290
|
+
// 2026-04-01T00:00:00.000Z -> 2026-04-30T23:59:59.999Z
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Parameters:
|
|
294
|
+
|
|
295
|
+
| Parameter | Type | Required | Values |
|
|
296
|
+
| --- | --- | --- | --- |
|
|
297
|
+
| `PERIOD` | `string` | Yes | `DAY`, `WEEK`, `MONTH`, `QUARTER` |
|
|
298
|
+
| `POSITION` | Integer `number` or `string` | Yes | Number, `FIRST`, `LAST` |
|
|
299
|
+
| `YEAR` | Integer `number` | No | Default: current year |
|
|
300
|
+
|
|
301
|
+
Examples:
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
PERIOD_AT("QUARTER", 2, 2026)
|
|
305
|
+
// 2026-04-01T00:00:00.000Z -> 2026-06-30T23:59:59.999Z
|
|
306
|
+
|
|
307
|
+
PERIOD_AT("MONTH", "LAST", 2025)
|
|
308
|
+
// 2025-12-01T00:00:00.000Z -> 2025-12-31T23:59:59.999Z
|
|
309
|
+
|
|
310
|
+
PERIOD_AT("WEEK", "LAST", 2028)
|
|
311
|
+
// 2028-12-31T00:00:00.000Z -> 2029-01-06T23:59:59.999Z
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Week rules:
|
|
315
|
+
|
|
316
|
+
- For `WEEK`, the start of the year is anchored to the start of the week that falls on or before the start of the year.
|
|
317
|
+
- The last week can cross into the next year.
|
|
318
|
+
- Numeric `POSITION` does not force an error if it points to a computable range outside the nominal year. For example, W54 can resolve by shifting even when the year does not nominally have W54.
|
|
319
|
+
- `"MIDDLE"` and other strings different from `FIRST` or `LAST` are invalid.
|
|
320
|
+
|
|
321
|
+
Output: `dateRange`.
|
|
322
|
+
|
|
323
|
+
Current value type: `relative`.
|
|
324
|
+
|
|
325
|
+
### `PARTIAL_DATE(year?, month?, quarter?, week?, day?)`
|
|
326
|
+
|
|
327
|
+
Represents a partial or recurring date. Each field can be a number or `"ANY"`. Omitted fields are treated as `ANY`.
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
PARTIAL_DATE("ANY", 4, "ANY", "ANY", 15)
|
|
331
|
+
// { month: 4, day: 15 }
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Parameters:
|
|
335
|
+
|
|
336
|
+
| Position | Field | Range | Example |
|
|
337
|
+
| --- | --- | --- | --- |
|
|
338
|
+
| 1 | `YEAR` | Integer or `ANY` | `2026` |
|
|
339
|
+
| 2 | `MONTH` | 1-12 or `ANY` | `4` |
|
|
340
|
+
| 3 | `QUARTER` | 1-4 or `ANY` | `2` |
|
|
341
|
+
| 4 | `WEEK` | 1-54 or `ANY` | `40` |
|
|
342
|
+
| 5 | `DAY` | 1-31 or `ANY` | `15` |
|
|
343
|
+
|
|
344
|
+
Date picker examples:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
PARTIAL_DATE()
|
|
348
|
+
// {}
|
|
349
|
+
// Short format: Any date
|
|
350
|
+
|
|
351
|
+
PARTIAL_DATE("ANY", 4)
|
|
352
|
+
// { month: 4 }
|
|
353
|
+
// Short format: Apr
|
|
354
|
+
|
|
355
|
+
PARTIAL_DATE("ANY", 4, "ANY", "ANY", 15)
|
|
356
|
+
// { month: 4, day: 15 }
|
|
357
|
+
// Short format: Apr 15
|
|
358
|
+
|
|
359
|
+
PARTIAL_DATE("ANY", "ANY", 2)
|
|
360
|
+
// { quarter: 2 }
|
|
361
|
+
// Short format: Q2
|
|
362
|
+
|
|
363
|
+
PARTIAL_DATE("ANY", "ANY", "ANY", 40)
|
|
364
|
+
// { week: 40 }
|
|
365
|
+
// Short format: W40
|
|
366
|
+
|
|
367
|
+
PARTIAL_DATE("ANY", "ANY", "ANY", "ANY", 15)
|
|
368
|
+
// { day: 15 }
|
|
369
|
+
// Short format: Day 15
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Value type:
|
|
373
|
+
|
|
374
|
+
- `fixed` if it includes `year`, `month`, and `day`, without `week`.
|
|
375
|
+
- `relative` if it includes `week`.
|
|
376
|
+
- `recurring` for all other partial dates.
|
|
377
|
+
|
|
378
|
+
### `START_OF(value)`
|
|
379
|
+
|
|
380
|
+
Returns the start of a `date` or the `start` of a `dateRange`.
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
START_OF(DATE("2026-07-08T15:30"))
|
|
384
|
+
// 2026-07-08T00:00:00.000Z
|
|
385
|
+
|
|
386
|
+
START_OF(CALENDAR_PERIOD("MONTH", -1))
|
|
387
|
+
// 2026-06-01T00:00:00.000Z
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Parameter:
|
|
391
|
+
|
|
392
|
+
| Parameter | Type |
|
|
393
|
+
| --- | --- |
|
|
394
|
+
| `VALUE` | `date` or `dateRange` |
|
|
395
|
+
|
|
396
|
+
Output: `date`.
|
|
397
|
+
|
|
398
|
+
Value type when used as root: `relative`.
|
|
399
|
+
|
|
400
|
+
### `END_OF(value)`
|
|
401
|
+
|
|
402
|
+
Returns the end of a `date` or the `end` of a `dateRange`.
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
END_OF(DATE("2026-07-08T15:30"))
|
|
406
|
+
// 2026-07-08T23:59:59.999Z
|
|
407
|
+
|
|
408
|
+
END_OF(CALENDAR_PERIOD("YEAR", -1))
|
|
409
|
+
// 2025-12-31T23:59:59.999Z
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Parameter:
|
|
413
|
+
|
|
414
|
+
| Parameter | Type |
|
|
415
|
+
| --- | --- |
|
|
416
|
+
| `VALUE` | `date` or `dateRange` |
|
|
417
|
+
|
|
418
|
+
Output: `date`.
|
|
419
|
+
|
|
420
|
+
Value type when used as root: `relative`.
|
|
421
|
+
|
|
422
|
+
### `PART(date, part)`
|
|
423
|
+
|
|
424
|
+
Extracts one part of a date.
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
PART(DATE("2026-07-08T15:30"), "DAY_OF_WEEK_NAME")
|
|
428
|
+
// Wednesday
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Parameters:
|
|
432
|
+
|
|
433
|
+
| Parameter | Type | Values |
|
|
434
|
+
| --- | --- | --- |
|
|
435
|
+
| `DATE` | `date` | Resolved ISO date |
|
|
436
|
+
| `PART` | `string` | See the table below |
|
|
437
|
+
|
|
438
|
+
Supported parts:
|
|
439
|
+
|
|
440
|
+
| Value | Output |
|
|
441
|
+
| --- | --- |
|
|
442
|
+
| `YEAR` | UTC year |
|
|
443
|
+
| `QUARTER` | Quarter 1-4 |
|
|
444
|
+
| `MONTH` | Month 1-12 |
|
|
445
|
+
| `MONTH_NAME` | English month name |
|
|
446
|
+
| `DAY` | Day of month |
|
|
447
|
+
| `DAY_OF_MONTH` | Day of month |
|
|
448
|
+
| `DAY_OF_WEEK` | UTC weekday, Sunday = 0 |
|
|
449
|
+
| `DAY_OF_WEEK_NAME` | English weekday name |
|
|
450
|
+
| `DAY_OF_YEAR` | Day of year |
|
|
451
|
+
| `WEEK_OF_YEAR` | Week according to the current convention |
|
|
452
|
+
| `HOUR` | UTC hour |
|
|
453
|
+
| `MINUTE` | UTC minute |
|
|
454
|
+
| `SECOND` | UTC second |
|
|
455
|
+
|
|
456
|
+
Important: `PART` is available as a QDP function, but it is not a valid final result for `TranspileDatePreset` because it returns `string`. It can be used as a helper function when accessing the QDP transpiler directly, but a final date preset expression must return `date`, `dateRange`, or `partialDate`.
|
|
457
|
+
|
|
458
|
+
## Differences Between Period Functions
|
|
459
|
+
|
|
460
|
+
| Function | Question it answers | Example | Type |
|
|
461
|
+
| --- | --- | --- | --- |
|
|
462
|
+
| `CALENDAR_PERIOD` | What is this/previous/next calendar period? | This month, last week | `relative` |
|
|
463
|
+
| `PERIOD_AT` | What is period N inside a year? | April 2026, Q2 2026, W40 2026 | Current `relative` |
|
|
464
|
+
| `RELATIVE_PERIOD` | What is the moving window from today/anchor? | Last 30 days | `rolling` |
|
|
465
|
+
|
|
466
|
+
Examples with current date `2026-07-22`:
|
|
467
|
+
|
|
468
|
+
```ts
|
|
469
|
+
CALENDAR_PERIOD("MONTH", -1)
|
|
470
|
+
// previous calendar month: Jun 1 -> Jun 30
|
|
471
|
+
|
|
472
|
+
PERIOD_AT("MONTH", 4, 2026)
|
|
473
|
+
// fourth month of 2026: Apr 1 -> Apr 30
|
|
474
|
+
|
|
475
|
+
RELATIVE_PERIOD(-29, "DAY")
|
|
476
|
+
// last 30 days inclusive: Jun 23 -> Jul 22
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
It is not recommended to merge them into a single public function because they express different concepts. If unification is desired, the best layer is the picker JSON/contract, which can then compile to these explicit QDP functions.
|
|
480
|
+
|
|
481
|
+
## Supported JSON
|
|
482
|
+
|
|
483
|
+
`TranspileJSONToDatePreset` accepts legacy tokens as strings or JSON nodes.
|
|
484
|
+
|
|
485
|
+
### Expression Nodes
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
{ type: 'NOW' }
|
|
489
|
+
{ type: 'TODAY' }
|
|
490
|
+
{ type: 'DATE', value: '2026-07-20' }
|
|
491
|
+
{ type: 'DATE_RANGE', start: DatePresetJSON, end: DatePresetJSON }
|
|
492
|
+
{ type: 'PARTIAL_DATE', value: { year?, quarter?, month?, week?, day? } }
|
|
493
|
+
{ type: 'RELATIVE_PERIOD', offset: -30, unit: 'DAY', anchor?: DatePresetJSON }
|
|
494
|
+
{ type: 'CALENDAR_PERIOD', period: 'MONTH', offset?: 0 }
|
|
495
|
+
{ type: 'PERIOD_AT', period: 'MONTH', position: 4 | 'FIRST' | 'LAST', year?: 2026 }
|
|
496
|
+
{ type: 'START_OF', input: DatePresetJSON }
|
|
497
|
+
{ type: 'END_OF', input: DatePresetJSON }
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Example:
|
|
501
|
+
|
|
502
|
+
```ts
|
|
503
|
+
TranspileJSONToDatePreset({
|
|
504
|
+
type: 'PERIOD_AT',
|
|
505
|
+
period: 'WEEK',
|
|
506
|
+
position: 'LAST',
|
|
507
|
+
year: 2028,
|
|
508
|
+
})
|
|
509
|
+
// PERIOD_AT("WEEK", "LAST", 2028)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Form JSON
|
|
513
|
+
|
|
514
|
+
Date picker oriented shapes are also supported:
|
|
515
|
+
|
|
516
|
+
```ts
|
|
517
|
+
{ type: 'SINGLE_PERIOD', date: { year: 2026, month: 7 } }
|
|
518
|
+
// DATE_RANGE(DATE("2026-07-01"), END_OF(DATE("2026-07-31")))
|
|
519
|
+
|
|
520
|
+
{ type: 'SINGLE_PERIOD', period: 'month', offset: -1 }
|
|
521
|
+
// CALENDAR_PERIOD("MONTH", -1)
|
|
522
|
+
|
|
523
|
+
{ type: 'CUSTOM_RANGE', from: { year: 2026, month: 5, day: 31 }, to: { year: 2026, month: 6, day: 30 } }
|
|
524
|
+
// DATE_RANGE(DATE("2026-05-31"), END_OF(DATE("2026-06-30")))
|
|
525
|
+
|
|
526
|
+
{ type: 'ROLLING_WINDOW', direction: 'last', amount: 30, unit: 'days' }
|
|
527
|
+
// RELATIVE_PERIOD(-30, "DAY")
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Rules:
|
|
531
|
+
|
|
532
|
+
- `SINGLE_PERIOD` with `date` requires `year`.
|
|
533
|
+
- `CUSTOM_RANGE` materializes dates with start-of-day and end-of-day boundaries.
|
|
534
|
+
- `ROLLING_WINDOW` normalizes plural units by removing the final `s`.
|
|
535
|
+
- `direction: 'NEXT'` produces a positive offset; any other value behaves as `LAST`.
|
|
536
|
+
|
|
537
|
+
## Formatting
|
|
538
|
+
|
|
539
|
+
`FormatDatePreset` formats values using `Intl.DateTimeFormat`.
|
|
540
|
+
|
|
541
|
+
By default, `date` and `dateRange` values include time using `timeStyle: 'short'`. When `partialDateStyle: 'short'` is used and no explicit `timeStyle` is provided, `date` and `dateRange` values omit time so they align with picker-style labels. Passing `timeStyle` explicitly keeps time in the output.
|
|
542
|
+
|
|
543
|
+
Main options:
|
|
544
|
+
|
|
545
|
+
```ts
|
|
546
|
+
{
|
|
547
|
+
locale?: 'en-US',
|
|
548
|
+
timezone?: 'UTC',
|
|
549
|
+
dateStyle?: 'full' | 'long' | 'medium' | 'short',
|
|
550
|
+
timeStyle?: 'full' | 'long' | 'medium' | 'short',
|
|
551
|
+
partialDateStyle?: 'long' | 'short'
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Examples:
|
|
556
|
+
|
|
557
|
+
```ts
|
|
558
|
+
FormatDatePreset('2026-07-15T14:35:27.000Z', {
|
|
559
|
+
locale: 'en-US',
|
|
560
|
+
timezone: 'America/Chicago',
|
|
561
|
+
dateStyle: 'medium',
|
|
562
|
+
timeStyle: 'short',
|
|
563
|
+
})
|
|
564
|
+
// Jul 15, 2026, 9:35 AM
|
|
565
|
+
|
|
566
|
+
FormatDatePreset('2026-07-15T14:35:27.000Z', { partialDateStyle: 'short' })
|
|
567
|
+
// Jul 15, 2026
|
|
568
|
+
|
|
569
|
+
FormatDatePreset(
|
|
570
|
+
{ start: '2026-07-01T00:00:00.000Z', end: '2026-07-31T23:59:59.999Z' },
|
|
571
|
+
{ partialDateStyle: 'short' },
|
|
572
|
+
)
|
|
573
|
+
// { start: 'Jul 1, 2026', end: 'Jul 31, 2026' }
|
|
574
|
+
|
|
575
|
+
FormatDatePreset({ month: 4, day: 15 })
|
|
576
|
+
// April 15
|
|
577
|
+
|
|
578
|
+
FormatDatePreset({ month: 4, day: 15 }, { partialDateStyle: 'short' })
|
|
579
|
+
// Apr 15
|
|
580
|
+
|
|
581
|
+
FormatDatePreset({ week: 40 }, { partialDateStyle: 'short' })
|
|
582
|
+
// W40
|
|
583
|
+
|
|
584
|
+
FormatDatePreset({ day: 15 }, { partialDateStyle: 'short' })
|
|
585
|
+
// Day 15
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
## Legacy Tokens
|
|
589
|
+
|
|
590
|
+
Legacy tokens are resolved with `TranspileJSONToDatePreset(token)` using `DATE_PRESET_TOKEN_MAP`.
|
|
591
|
+
|
|
592
|
+
| Token | QDP expression |
|
|
593
|
+
| --- | --- |
|
|
594
|
+
| `NOW` | `NOW()` |
|
|
595
|
+
| `TODAY` | `TODAY()` |
|
|
596
|
+
| `CURRENT_DATE` | `TODAY()` |
|
|
597
|
+
| `TODAY-7` | `START_OF(RELATIVE_PERIOD(-7, "DAY"))` |
|
|
598
|
+
| `TODAY-30` | `START_OF(RELATIVE_PERIOD(-30, "DAY"))` |
|
|
599
|
+
| `TODAY-60` | `START_OF(RELATIVE_PERIOD(-60, "DAY"))` |
|
|
600
|
+
| `TODAY-90` | `START_OF(RELATIVE_PERIOD(-90, "DAY"))` |
|
|
601
|
+
| `TODAY-120` | `START_OF(RELATIVE_PERIOD(-120, "DAY"))` |
|
|
602
|
+
| `TODAY-365` | `START_OF(RELATIVE_PERIOD(-365, "DAY"))` |
|
|
603
|
+
| `YESTERDAY` | `START_OF(RELATIVE_PERIOD(-1, "DAY"))` |
|
|
604
|
+
| `TOMORROW` | `START_OF(END_OF(RELATIVE_PERIOD(1, "DAY")))` |
|
|
605
|
+
| `CURRENT_MONTH` | `CALENDAR_PERIOD("MONTH", 0)` |
|
|
606
|
+
| `CURRENT_MONTH_START` | `START_OF(CALENDAR_PERIOD("MONTH", 0))` |
|
|
607
|
+
| `CURRENT_MONTH_END` | `END_OF(CALENDAR_PERIOD("MONTH", 0))` |
|
|
608
|
+
| `LAST_MONTH` | `CALENDAR_PERIOD("MONTH", -1)` |
|
|
609
|
+
| `LAST_MONTH_START` | `START_OF(CALENDAR_PERIOD("MONTH", -1))` |
|
|
610
|
+
| `LAST_MONTH_END` | `END_OF(CALENDAR_PERIOD("MONTH", -1))` |
|
|
611
|
+
| `CURRENT_WEEK` | `CALENDAR_PERIOD("WEEK", 0)` |
|
|
612
|
+
| `CURRENT_WEEK_START` | `START_OF(CALENDAR_PERIOD("WEEK", 0))` |
|
|
613
|
+
| `CURRENT_WEEK_END` | `END_OF(CALENDAR_PERIOD("WEEK", 0))` |
|
|
614
|
+
| `LAST_WEEK` | `CALENDAR_PERIOD("WEEK", -1)` |
|
|
615
|
+
| `LAST_WEEK_START` | `START_OF(CALENDAR_PERIOD("WEEK", -1))` |
|
|
616
|
+
| `LAST_WEEK_END` | `END_OF(CALENDAR_PERIOD("WEEK", -1))` |
|
|
617
|
+
| `CURRENT_QUARTER` | `CALENDAR_PERIOD("QUARTER", 0)` |
|
|
618
|
+
| `CURRENT_QUARTER_START` | `START_OF(CALENDAR_PERIOD("QUARTER", 0))` |
|
|
619
|
+
| `CURRENT_QUARTER_END` | `END_OF(CALENDAR_PERIOD("QUARTER", 0))` |
|
|
620
|
+
| `LAST_QUARTER` | `CALENDAR_PERIOD("QUARTER", -1)` |
|
|
621
|
+
| `LAST_QUARTER_START` | `START_OF(CALENDAR_PERIOD("QUARTER", -1))` |
|
|
622
|
+
| `LAST_QUARTER_END` | `END_OF(CALENDAR_PERIOD("QUARTER", -1))` |
|
|
623
|
+
| `CURRENT_YEAR` | `CALENDAR_PERIOD("YEAR", 0)` |
|
|
624
|
+
| `CURRENT_YEAR_START` | `START_OF(CALENDAR_PERIOD("YEAR", 0))` |
|
|
625
|
+
| `LAST_YEAR` | `CALENDAR_PERIOD("YEAR", -1)` |
|
|
626
|
+
| `LAST_YEAR_START` | `START_OF(CALENDAR_PERIOD("YEAR", -1))` |
|
|
627
|
+
| `LAST_YEAR_END` | `END_OF(CALENDAR_PERIOD("YEAR", -1))` |
|
|
628
|
+
| `YEAR_BEFORE_LAST_YEAR_START` | `START_OF(CALENDAR_PERIOD("YEAR", -2))` |
|
|
629
|
+
| `YEAR_BEFORE_LAST_YEAR_END` | `END_OF(CALENDAR_PERIOD("YEAR", -2))` |
|
|
630
|
+
|
|
631
|
+
Tokens can be wrapped like `{{TODAY-7}}`. The normalizer removes braces and outer spaces.
|
|
632
|
+
|
|
633
|
+
Scalar tokens such as `CURRENT_TIME`, `CURRENT_TIMEZONE`, and `CURRENT_DAY_OF_WEEK` are not supported as date presets because they do not return `date`, `dateRange`, or `partialDate`.
|
|
634
|
+
|
|
635
|
+
## Main Equivalences With The Date Picker
|
|
636
|
+
|
|
637
|
+
| Picker expression | QDP expression | Note |
|
|
638
|
+
| --- | --- | --- |
|
|
639
|
+
| Today | `TODAY()` | Fixed date at the start of the current day |
|
|
640
|
+
| Yesterday | `START_OF(RELATIVE_PERIOD(-1, "DAY"))` | Start of yesterday |
|
|
641
|
+
| Tomorrow | `START_OF(END_OF(RELATIVE_PERIOD(1, "DAY")))` | Start of tomorrow |
|
|
642
|
+
| This month | `CALENDAR_PERIOD("MONTH", 0)` | Current calendar month |
|
|
643
|
+
| Previous month | `CALENDAR_PERIOD("MONTH", -1)` | Previous calendar month |
|
|
644
|
+
| Last 30 days inclusive | `RELATIVE_PERIOD(-29, "DAY")` | Inclusive 30-day rolling window counting today |
|
|
645
|
+
| April | `PARTIAL_DATE("ANY", 4)` | Recurring month |
|
|
646
|
+
| April 2026 | `PERIOD_AT("MONTH", 4, 2026)` | Positional month in a year |
|
|
647
|
+
| Apr 15 | `PARTIAL_DATE("ANY", 4, "ANY", "ANY", 15)` | Recurring month/day |
|
|
648
|
+
| Day 15 | `PARTIAL_DATE("ANY", "ANY", "ANY", "ANY", 15)` | Recurring day of month |
|
|
649
|
+
| Q2 | `PARTIAL_DATE("ANY", "ANY", 2)` | Recurring quarter |
|
|
650
|
+
| Q2 2026 | `PERIOD_AT("QUARTER", 2, 2026)` | Positional quarter in a year |
|
|
651
|
+
| W40 | `PARTIAL_DATE("ANY", "ANY", "ANY", 40)` | Recurring week |
|
|
652
|
+
| W40 2026 | `PERIOD_AT("WEEK", 40, 2026)` | Positional week in a year |
|
|
653
|
+
| Last week of 2028 | `PERIOD_AT("WEEK", "LAST", 2028)` | Avoids assuming W53/W54 |
|
|
654
|
+
| Last month of the past year | `PERIOD_AT("MONTH", "LAST", 2025)` | Equivalent to December 2025 with current date 2026 |
|
|
655
|
+
| Between inclusive | `DATE_RANGE(DATE(start), END_OF(DATE(end)))` | Materialize inclusive boundaries |
|
|
656
|
+
| Between exclusive | `DATE_RANGE(DATE(adjustedStart), END_OF(DATE(adjustedEnd)))` | Materialize exclusion in the dates |
|
|
657
|
+
|
|
658
|
+
## Validations And Expected Errors
|
|
659
|
+
|
|
660
|
+
Important invalid cases:
|
|
661
|
+
|
|
662
|
+
```ts
|
|
663
|
+
DATE("2026-02-31")
|
|
664
|
+
// INVALID_ALLOW_VALUE: calendrically invalid date
|
|
665
|
+
|
|
666
|
+
DATE("2026-02-31T00:00")
|
|
667
|
+
// INVALID_ALLOW_VALUE: calendrically invalid date
|
|
668
|
+
|
|
669
|
+
RELATIVE_PERIOD(-1, "HOUR")
|
|
670
|
+
// INVALID_ALLOW_VALUE: unsupported unit
|
|
671
|
+
|
|
672
|
+
CALENDAR_PERIOD("DECADE", 0)
|
|
673
|
+
// INVALID_ALLOW_VALUE: unsupported period
|
|
674
|
+
|
|
675
|
+
PERIOD_AT("MONTH", "MIDDLE", 2026)
|
|
676
|
+
// INVALID_ALLOW_VALUE: unsupported symbolic position
|
|
677
|
+
|
|
678
|
+
PARTIAL_DATE("ANY", 13)
|
|
679
|
+
// INVALID_ALLOW_VALUE: month out of range
|
|
680
|
+
|
|
681
|
+
DATE_RANGE(DATE("2026-07-31T00:00"), DATE("2026-07-01T00:00"))
|
|
682
|
+
// INVALID_DATE_RANGE: end before start
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
Additionally, any QDP expression whose final result is not `date`, `dateRange`, or `partialDate` returns `INVALID_DATE_PRESET_RESULT`.
|
|
686
|
+
|
|
687
|
+
## Relevant Files
|
|
688
|
+
|
|
689
|
+
| File | Responsibility |
|
|
690
|
+
| --- | --- |
|
|
691
|
+
| `src/date-presets.ts` | Public API, JSON conversion, formatting, and `valueType` classification |
|
|
692
|
+
| `src/date-preset-tokens.ts` | Legacy token map to QDP expressions |
|
|
693
|
+
| `src/functions/index.ts` | Function registration for `ENGINES.QDP` |
|
|
694
|
+
| `src/functions/datePresetUtils.ts` | Date, range, calendar, week, timezone, and partial date resolution |
|
|
695
|
+
| `src/functions/*.ts` | Individual QDP function definitions |
|
|
696
|
+
| `__tests__/unit/datePresetTranspiler.test.ts` | Main transpilation and picker compatibility cases |
|
|
697
|
+
| `__tests__/unit/datePresetJson.test.ts` | JSON to QDP conversion |
|
|
698
|
+
| `__tests__/unit/datePresetFormat.test.ts` | Date and partial date formatting |
|
|
699
|
+
| `__tests__/unit/datePresetTokens.test.ts` | Legacy tokens |
|
|
700
|
+
| `date-preset-qdp-examples.csv` | Generated examples with tokens and picker expressions |
|
|
701
|
+
|
|
702
|
+
## Current State And Design Notes
|
|
703
|
+
|
|
704
|
+
- QDP is limited to date preset functions in `ENGINE_FN_MAP[ENGINES.QDP]`.
|
|
705
|
+
- Date preset expressions can be nested as long as the final result is `date`, `dateRange`, or `partialDate`.
|
|
706
|
+
- `partialDate` was added as a primitive to represent incomplete date picker selections.
|
|
707
|
+
- Week compatibility with the date picker uses Sunday as the default start day and supports W54.
|
|
708
|
+
- `PERIOD_AT` supports symbolic positions `FIRST` and `LAST` to reduce ambiguity in variable-length periods.
|
|
709
|
+
- For documentation and example auditing, the CSV `date-preset-qdp-examples.csv` contains resolved, formatted, and classified values.
|