@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.
Files changed (377) hide show
  1. package/QRVEY-DATE-PRESETS.md +709 -0
  2. package/README.md +22 -0
  3. package/dist/cjs/constants/index.d.ts +5 -1
  4. package/dist/cjs/constants/index.js +4 -0
  5. package/dist/cjs/constants/index.js.map +1 -1
  6. package/dist/cjs/constants/interfaces.d.ts +38 -4
  7. package/dist/cjs/date-preset-tokens.d.ts +40 -0
  8. package/dist/cjs/date-preset-tokens.js +52 -0
  9. package/dist/cjs/date-preset-tokens.js.map +1 -0
  10. package/dist/cjs/date-presets.d.ts +65 -0
  11. package/dist/cjs/date-presets.js +319 -0
  12. package/dist/cjs/date-presets.js.map +1 -0
  13. package/dist/cjs/errors/analyzer/clickhouse.d.ts +8 -0
  14. package/dist/cjs/errors/analyzer/clickhouse.js +31 -0
  15. package/dist/cjs/errors/analyzer/clickhouse.js.map +1 -0
  16. package/dist/cjs/errors/analyzer/index.js +6 -1
  17. package/dist/cjs/errors/analyzer/index.js.map +1 -1
  18. package/dist/cjs/functions/abs.js +4 -0
  19. package/dist/cjs/functions/abs.js.map +1 -1
  20. package/dist/cjs/functions/aggAvg.js +6 -0
  21. package/dist/cjs/functions/aggAvg.js.map +1 -1
  22. package/dist/cjs/functions/aggCount.js +6 -0
  23. package/dist/cjs/functions/aggCount.js.map +1 -1
  24. package/dist/cjs/functions/aggDistcount.js +6 -0
  25. package/dist/cjs/functions/aggDistcount.js.map +1 -1
  26. package/dist/cjs/functions/aggMax.js +4 -0
  27. package/dist/cjs/functions/aggMax.js.map +1 -1
  28. package/dist/cjs/functions/aggMed.js +5 -0
  29. package/dist/cjs/functions/aggMed.js.map +1 -1
  30. package/dist/cjs/functions/aggMin.js +4 -0
  31. package/dist/cjs/functions/aggMin.js.map +1 -1
  32. package/dist/cjs/functions/aggSum.js +5 -0
  33. package/dist/cjs/functions/aggSum.js.map +1 -1
  34. package/dist/cjs/functions/and.js +4 -0
  35. package/dist/cjs/functions/and.js.map +1 -1
  36. package/dist/cjs/functions/calendarPeriod.d.ts +2 -0
  37. package/dist/cjs/functions/calendarPeriod.js +46 -0
  38. package/dist/cjs/functions/calendarPeriod.js.map +1 -0
  39. package/dist/cjs/functions/concatenate.js +4 -0
  40. package/dist/cjs/functions/concatenate.js.map +1 -1
  41. package/dist/cjs/functions/date.d.ts +2 -0
  42. package/dist/cjs/functions/date.js +27 -0
  43. package/dist/cjs/functions/date.js.map +1 -0
  44. package/dist/cjs/functions/datePresetUtils.d.ts +31 -0
  45. package/dist/cjs/functions/datePresetUtils.js +621 -0
  46. package/dist/cjs/functions/datePresetUtils.js.map +1 -0
  47. package/dist/cjs/functions/dateRange.d.ts +2 -0
  48. package/dist/cjs/functions/dateRange.js +38 -0
  49. package/dist/cjs/functions/dateRange.js.map +1 -0
  50. package/dist/cjs/functions/dateadd.js +21 -0
  51. package/dist/cjs/functions/dateadd.js.map +1 -1
  52. package/dist/cjs/functions/datedif.js +6 -0
  53. package/dist/cjs/functions/datedif.js.map +1 -1
  54. package/dist/cjs/functions/datesubtract.js +21 -0
  55. package/dist/cjs/functions/datesubtract.js.map +1 -1
  56. package/dist/cjs/functions/day.js +4 -0
  57. package/dist/cjs/functions/day.js.map +1 -1
  58. package/dist/cjs/functions/dayofweek.js +14 -0
  59. package/dist/cjs/functions/dayofweek.js.map +1 -1
  60. package/dist/cjs/functions/endOf.d.ts +2 -0
  61. package/dist/cjs/functions/endOf.js +26 -0
  62. package/dist/cjs/functions/endOf.js.map +1 -0
  63. package/dist/cjs/functions/even.js +4 -0
  64. package/dist/cjs/functions/even.js.map +1 -1
  65. package/dist/cjs/functions/exp.js +4 -0
  66. package/dist/cjs/functions/exp.js.map +1 -1
  67. package/dist/cjs/functions/hour.js +12 -0
  68. package/dist/cjs/functions/hour.js.map +1 -1
  69. package/dist/cjs/functions/if.js +4 -0
  70. package/dist/cjs/functions/if.js.map +1 -1
  71. package/dist/cjs/functions/ifs.js +4 -0
  72. package/dist/cjs/functions/ifs.js.map +1 -1
  73. package/dist/cjs/functions/include.js +4 -0
  74. package/dist/cjs/functions/include.js.map +1 -1
  75. package/dist/cjs/functions/index.js +40 -4
  76. package/dist/cjs/functions/index.js.map +1 -1
  77. package/dist/cjs/functions/isNull.js +4 -0
  78. package/dist/cjs/functions/isNull.js.map +1 -1
  79. package/dist/cjs/functions/left.js +10 -0
  80. package/dist/cjs/functions/left.js.map +1 -1
  81. package/dist/cjs/functions/length.js +8 -0
  82. package/dist/cjs/functions/length.js.map +1 -1
  83. package/dist/cjs/functions/log.js +10 -0
  84. package/dist/cjs/functions/log.js.map +1 -1
  85. package/dist/cjs/functions/lower.js +5 -0
  86. package/dist/cjs/functions/lower.js.map +1 -1
  87. package/dist/cjs/functions/max.js +4 -0
  88. package/dist/cjs/functions/max.js.map +1 -1
  89. package/dist/cjs/functions/mid.js +16 -0
  90. package/dist/cjs/functions/mid.js.map +1 -1
  91. package/dist/cjs/functions/millisecond.js +8 -0
  92. package/dist/cjs/functions/millisecond.js.map +1 -1
  93. package/dist/cjs/functions/min.js +4 -0
  94. package/dist/cjs/functions/min.js.map +1 -1
  95. package/dist/cjs/functions/minute.js +4 -0
  96. package/dist/cjs/functions/minute.js.map +1 -1
  97. package/dist/cjs/functions/month.js +4 -0
  98. package/dist/cjs/functions/month.js.map +1 -1
  99. package/dist/cjs/functions/now.js +8 -0
  100. package/dist/cjs/functions/now.js.map +1 -1
  101. package/dist/cjs/functions/odd.js +4 -0
  102. package/dist/cjs/functions/odd.js.map +1 -1
  103. package/dist/cjs/functions/or.js +4 -0
  104. package/dist/cjs/functions/or.js.map +1 -1
  105. package/dist/cjs/functions/part.d.ts +2 -0
  106. package/dist/cjs/functions/part.js +52 -0
  107. package/dist/cjs/functions/part.js.map +1 -0
  108. package/dist/cjs/functions/partialDate.d.ts +2 -0
  109. package/dist/cjs/functions/partialDate.js +56 -0
  110. package/dist/cjs/functions/partialDate.js.map +1 -0
  111. package/dist/cjs/functions/periodAt.d.ts +2 -0
  112. package/dist/cjs/functions/periodAt.js +61 -0
  113. package/dist/cjs/functions/periodAt.js.map +1 -0
  114. package/dist/cjs/functions/power.js +4 -0
  115. package/dist/cjs/functions/power.js.map +1 -1
  116. package/dist/cjs/functions/proper.js +4 -0
  117. package/dist/cjs/functions/proper.js.map +1 -1
  118. package/dist/cjs/functions/random.js +4 -0
  119. package/dist/cjs/functions/random.js.map +1 -1
  120. package/dist/cjs/functions/relativePeriod.d.ts +2 -0
  121. package/dist/cjs/functions/relativePeriod.js +52 -0
  122. package/dist/cjs/functions/relativePeriod.js.map +1 -0
  123. package/dist/cjs/functions/replace.js +4 -0
  124. package/dist/cjs/functions/replace.js.map +1 -1
  125. package/dist/cjs/functions/right.js +10 -0
  126. package/dist/cjs/functions/right.js.map +1 -1
  127. package/dist/cjs/functions/round.js +17 -0
  128. package/dist/cjs/functions/round.js.map +1 -1
  129. package/dist/cjs/functions/rounddown.js +9 -0
  130. package/dist/cjs/functions/rounddown.js.map +1 -1
  131. package/dist/cjs/functions/roundup.js +9 -0
  132. package/dist/cjs/functions/roundup.js.map +1 -1
  133. package/dist/cjs/functions/second.js +4 -0
  134. package/dist/cjs/functions/second.js.map +1 -1
  135. package/dist/cjs/functions/sqrt.js +4 -0
  136. package/dist/cjs/functions/sqrt.js.map +1 -1
  137. package/dist/cjs/functions/startOf.d.ts +2 -0
  138. package/dist/cjs/functions/startOf.js +26 -0
  139. package/dist/cjs/functions/startOf.js.map +1 -0
  140. package/dist/cjs/functions/text.js +4 -0
  141. package/dist/cjs/functions/text.js.map +1 -1
  142. package/dist/cjs/functions/today.d.ts +2 -0
  143. package/dist/cjs/functions/today.js +20 -0
  144. package/dist/cjs/functions/today.js.map +1 -0
  145. package/dist/cjs/functions/totalAvg.js +6 -0
  146. package/dist/cjs/functions/totalAvg.js.map +1 -1
  147. package/dist/cjs/functions/totalCount.js +6 -0
  148. package/dist/cjs/functions/totalCount.js.map +1 -1
  149. package/dist/cjs/functions/totalDistcount.js +6 -0
  150. package/dist/cjs/functions/totalDistcount.js.map +1 -1
  151. package/dist/cjs/functions/totalMax.js +4 -0
  152. package/dist/cjs/functions/totalMax.js.map +1 -1
  153. package/dist/cjs/functions/totalMed.js +5 -0
  154. package/dist/cjs/functions/totalMed.js.map +1 -1
  155. package/dist/cjs/functions/totalMin.js +4 -0
  156. package/dist/cjs/functions/totalMin.js.map +1 -1
  157. package/dist/cjs/functions/totalSum.js +4 -0
  158. package/dist/cjs/functions/totalSum.js.map +1 -1
  159. package/dist/cjs/functions/trim.js +4 -0
  160. package/dist/cjs/functions/trim.js.map +1 -1
  161. package/dist/cjs/functions/upper.js +5 -0
  162. package/dist/cjs/functions/upper.js.map +1 -1
  163. package/dist/cjs/functions/year.js +4 -0
  164. package/dist/cjs/functions/year.js.map +1 -1
  165. package/dist/cjs/index.d.ts +3 -1
  166. package/dist/cjs/index.js +8 -1
  167. package/dist/cjs/index.js.map +1 -1
  168. package/dist/cjs/parser/engine-validators/index.js +1 -0
  169. package/dist/cjs/parser/engine-validators/index.js.map +1 -1
  170. package/dist/cjs/parser/json-parser.js +2 -0
  171. package/dist/cjs/parser/json-parser.js.map +1 -1
  172. package/dist/cjs/transpiler/columnTranspilation.js +13 -1
  173. package/dist/cjs/transpiler/columnTranspilation.js.map +1 -1
  174. package/dist/cjs/transpiler/index.d.ts +1 -0
  175. package/dist/cjs/transpiler/index.js +19 -3
  176. package/dist/cjs/transpiler/index.js.map +1 -1
  177. package/dist/cjs/utils/addDecimalPointIfNeeded.js +1 -0
  178. package/dist/cjs/utils/addDecimalPointIfNeeded.js.map +1 -1
  179. package/dist/cjs/utils/clickhouse/index.d.ts +1 -0
  180. package/dist/cjs/utils/clickhouse/index.js +8 -0
  181. package/dist/cjs/utils/clickhouse/index.js.map +1 -0
  182. package/dist/cjs/utils/clickhouse/scripts.d.ts +4 -0
  183. package/dist/cjs/utils/clickhouse/scripts.js +49 -0
  184. package/dist/cjs/utils/clickhouse/scripts.js.map +1 -0
  185. package/dist/cjs/utils/customFunctions.d.ts +1 -0
  186. package/dist/cjs/utils/customFunctions.js +15 -1
  187. package/dist/cjs/utils/customFunctions.js.map +1 -1
  188. package/dist/cjs/utils/isALiteral.js +11 -1
  189. package/dist/cjs/utils/isALiteral.js.map +1 -1
  190. package/dist/module/constants/index.d.ts +5 -1
  191. package/dist/module/constants/index.js +4 -0
  192. package/dist/module/constants/index.js.map +1 -1
  193. package/dist/module/constants/interfaces.d.ts +38 -4
  194. package/dist/module/date-preset-tokens.d.ts +40 -0
  195. package/dist/module/date-preset-tokens.js +48 -0
  196. package/dist/module/date-preset-tokens.js.map +1 -0
  197. package/dist/module/date-presets.d.ts +65 -0
  198. package/dist/module/date-presets.js +313 -0
  199. package/dist/module/date-presets.js.map +1 -0
  200. package/dist/module/errors/analyzer/clickhouse.d.ts +8 -0
  201. package/dist/module/errors/analyzer/clickhouse.js +27 -0
  202. package/dist/module/errors/analyzer/clickhouse.js.map +1 -0
  203. package/dist/module/errors/analyzer/index.js +6 -1
  204. package/dist/module/errors/analyzer/index.js.map +1 -1
  205. package/dist/module/functions/abs.js +4 -0
  206. package/dist/module/functions/abs.js.map +1 -1
  207. package/dist/module/functions/aggAvg.js +6 -0
  208. package/dist/module/functions/aggAvg.js.map +1 -1
  209. package/dist/module/functions/aggCount.js +6 -0
  210. package/dist/module/functions/aggCount.js.map +1 -1
  211. package/dist/module/functions/aggDistcount.js +6 -0
  212. package/dist/module/functions/aggDistcount.js.map +1 -1
  213. package/dist/module/functions/aggMax.js +4 -0
  214. package/dist/module/functions/aggMax.js.map +1 -1
  215. package/dist/module/functions/aggMed.js +5 -0
  216. package/dist/module/functions/aggMed.js.map +1 -1
  217. package/dist/module/functions/aggMin.js +4 -0
  218. package/dist/module/functions/aggMin.js.map +1 -1
  219. package/dist/module/functions/aggSum.js +5 -0
  220. package/dist/module/functions/aggSum.js.map +1 -1
  221. package/dist/module/functions/and.js +4 -0
  222. package/dist/module/functions/and.js.map +1 -1
  223. package/dist/module/functions/calendarPeriod.d.ts +2 -0
  224. package/dist/module/functions/calendarPeriod.js +43 -0
  225. package/dist/module/functions/calendarPeriod.js.map +1 -0
  226. package/dist/module/functions/concatenate.js +4 -0
  227. package/dist/module/functions/concatenate.js.map +1 -1
  228. package/dist/module/functions/date.d.ts +2 -0
  229. package/dist/module/functions/date.js +24 -0
  230. package/dist/module/functions/date.js.map +1 -0
  231. package/dist/module/functions/datePresetUtils.d.ts +31 -0
  232. package/dist/module/functions/datePresetUtils.js +601 -0
  233. package/dist/module/functions/datePresetUtils.js.map +1 -0
  234. package/dist/module/functions/dateRange.d.ts +2 -0
  235. package/dist/module/functions/dateRange.js +35 -0
  236. package/dist/module/functions/dateRange.js.map +1 -0
  237. package/dist/module/functions/dateadd.js +21 -0
  238. package/dist/module/functions/dateadd.js.map +1 -1
  239. package/dist/module/functions/datedif.js +6 -0
  240. package/dist/module/functions/datedif.js.map +1 -1
  241. package/dist/module/functions/datesubtract.js +21 -0
  242. package/dist/module/functions/datesubtract.js.map +1 -1
  243. package/dist/module/functions/day.js +4 -0
  244. package/dist/module/functions/day.js.map +1 -1
  245. package/dist/module/functions/dayofweek.js +14 -0
  246. package/dist/module/functions/dayofweek.js.map +1 -1
  247. package/dist/module/functions/endOf.d.ts +2 -0
  248. package/dist/module/functions/endOf.js +23 -0
  249. package/dist/module/functions/endOf.js.map +1 -0
  250. package/dist/module/functions/even.js +4 -0
  251. package/dist/module/functions/even.js.map +1 -1
  252. package/dist/module/functions/exp.js +4 -0
  253. package/dist/module/functions/exp.js.map +1 -1
  254. package/dist/module/functions/hour.js +12 -0
  255. package/dist/module/functions/hour.js.map +1 -1
  256. package/dist/module/functions/if.js +4 -0
  257. package/dist/module/functions/if.js.map +1 -1
  258. package/dist/module/functions/ifs.js +4 -0
  259. package/dist/module/functions/ifs.js.map +1 -1
  260. package/dist/module/functions/include.js +4 -0
  261. package/dist/module/functions/include.js.map +1 -1
  262. package/dist/module/functions/index.js +40 -4
  263. package/dist/module/functions/index.js.map +1 -1
  264. package/dist/module/functions/isNull.js +4 -0
  265. package/dist/module/functions/isNull.js.map +1 -1
  266. package/dist/module/functions/left.js +10 -0
  267. package/dist/module/functions/left.js.map +1 -1
  268. package/dist/module/functions/length.js +8 -0
  269. package/dist/module/functions/length.js.map +1 -1
  270. package/dist/module/functions/log.js +10 -0
  271. package/dist/module/functions/log.js.map +1 -1
  272. package/dist/module/functions/lower.js +5 -0
  273. package/dist/module/functions/lower.js.map +1 -1
  274. package/dist/module/functions/max.js +4 -0
  275. package/dist/module/functions/max.js.map +1 -1
  276. package/dist/module/functions/mid.js +16 -0
  277. package/dist/module/functions/mid.js.map +1 -1
  278. package/dist/module/functions/millisecond.js +8 -0
  279. package/dist/module/functions/millisecond.js.map +1 -1
  280. package/dist/module/functions/min.js +4 -0
  281. package/dist/module/functions/min.js.map +1 -1
  282. package/dist/module/functions/minute.js +4 -0
  283. package/dist/module/functions/minute.js.map +1 -1
  284. package/dist/module/functions/month.js +4 -0
  285. package/dist/module/functions/month.js.map +1 -1
  286. package/dist/module/functions/now.js +8 -0
  287. package/dist/module/functions/now.js.map +1 -1
  288. package/dist/module/functions/odd.js +4 -0
  289. package/dist/module/functions/odd.js.map +1 -1
  290. package/dist/module/functions/or.js +4 -0
  291. package/dist/module/functions/or.js.map +1 -1
  292. package/dist/module/functions/part.d.ts +2 -0
  293. package/dist/module/functions/part.js +49 -0
  294. package/dist/module/functions/part.js.map +1 -0
  295. package/dist/module/functions/partialDate.d.ts +2 -0
  296. package/dist/module/functions/partialDate.js +53 -0
  297. package/dist/module/functions/partialDate.js.map +1 -0
  298. package/dist/module/functions/periodAt.d.ts +2 -0
  299. package/dist/module/functions/periodAt.js +58 -0
  300. package/dist/module/functions/periodAt.js.map +1 -0
  301. package/dist/module/functions/power.js +4 -0
  302. package/dist/module/functions/power.js.map +1 -1
  303. package/dist/module/functions/proper.js +4 -0
  304. package/dist/module/functions/proper.js.map +1 -1
  305. package/dist/module/functions/random.js +4 -0
  306. package/dist/module/functions/random.js.map +1 -1
  307. package/dist/module/functions/relativePeriod.d.ts +2 -0
  308. package/dist/module/functions/relativePeriod.js +49 -0
  309. package/dist/module/functions/relativePeriod.js.map +1 -0
  310. package/dist/module/functions/replace.js +4 -0
  311. package/dist/module/functions/replace.js.map +1 -1
  312. package/dist/module/functions/right.js +10 -0
  313. package/dist/module/functions/right.js.map +1 -1
  314. package/dist/module/functions/round.js +17 -0
  315. package/dist/module/functions/round.js.map +1 -1
  316. package/dist/module/functions/rounddown.js +9 -0
  317. package/dist/module/functions/rounddown.js.map +1 -1
  318. package/dist/module/functions/roundup.js +9 -0
  319. package/dist/module/functions/roundup.js.map +1 -1
  320. package/dist/module/functions/second.js +4 -0
  321. package/dist/module/functions/second.js.map +1 -1
  322. package/dist/module/functions/sqrt.js +4 -0
  323. package/dist/module/functions/sqrt.js.map +1 -1
  324. package/dist/module/functions/startOf.d.ts +2 -0
  325. package/dist/module/functions/startOf.js +23 -0
  326. package/dist/module/functions/startOf.js.map +1 -0
  327. package/dist/module/functions/text.js +4 -0
  328. package/dist/module/functions/text.js.map +1 -1
  329. package/dist/module/functions/today.d.ts +2 -0
  330. package/dist/module/functions/today.js +17 -0
  331. package/dist/module/functions/today.js.map +1 -0
  332. package/dist/module/functions/totalAvg.js +6 -0
  333. package/dist/module/functions/totalAvg.js.map +1 -1
  334. package/dist/module/functions/totalCount.js +6 -0
  335. package/dist/module/functions/totalCount.js.map +1 -1
  336. package/dist/module/functions/totalDistcount.js +6 -0
  337. package/dist/module/functions/totalDistcount.js.map +1 -1
  338. package/dist/module/functions/totalMax.js +4 -0
  339. package/dist/module/functions/totalMax.js.map +1 -1
  340. package/dist/module/functions/totalMed.js +5 -0
  341. package/dist/module/functions/totalMed.js.map +1 -1
  342. package/dist/module/functions/totalMin.js +4 -0
  343. package/dist/module/functions/totalMin.js.map +1 -1
  344. package/dist/module/functions/totalSum.js +4 -0
  345. package/dist/module/functions/totalSum.js.map +1 -1
  346. package/dist/module/functions/trim.js +4 -0
  347. package/dist/module/functions/trim.js.map +1 -1
  348. package/dist/module/functions/upper.js +5 -0
  349. package/dist/module/functions/upper.js.map +1 -1
  350. package/dist/module/functions/year.js +4 -0
  351. package/dist/module/functions/year.js.map +1 -1
  352. package/dist/module/index.d.ts +3 -1
  353. package/dist/module/index.js +2 -0
  354. package/dist/module/index.js.map +1 -1
  355. package/dist/module/parser/engine-validators/index.js +1 -0
  356. package/dist/module/parser/engine-validators/index.js.map +1 -1
  357. package/dist/module/parser/json-parser.js +2 -0
  358. package/dist/module/parser/json-parser.js.map +1 -1
  359. package/dist/module/transpiler/columnTranspilation.js +13 -1
  360. package/dist/module/transpiler/columnTranspilation.js.map +1 -1
  361. package/dist/module/transpiler/index.d.ts +1 -0
  362. package/dist/module/transpiler/index.js +20 -4
  363. package/dist/module/transpiler/index.js.map +1 -1
  364. package/dist/module/utils/addDecimalPointIfNeeded.js +1 -0
  365. package/dist/module/utils/addDecimalPointIfNeeded.js.map +1 -1
  366. package/dist/module/utils/clickhouse/index.d.ts +1 -0
  367. package/dist/module/utils/clickhouse/index.js +2 -0
  368. package/dist/module/utils/clickhouse/index.js.map +1 -0
  369. package/dist/module/utils/clickhouse/scripts.d.ts +4 -0
  370. package/dist/module/utils/clickhouse/scripts.js +43 -0
  371. package/dist/module/utils/clickhouse/scripts.js.map +1 -0
  372. package/dist/module/utils/customFunctions.d.ts +1 -0
  373. package/dist/module/utils/customFunctions.js +13 -0
  374. package/dist/module/utils/customFunctions.js.map +1 -1
  375. package/dist/module/utils/isALiteral.js +12 -2
  376. package/dist/module/utils/isALiteral.js.map +1 -1
  377. 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.