ObjectStackObjectStack

Date Macros

Date Macros protocol schemas

Date Macro Tokens — the declarative placeholders the UI substitutes

into filter values before sending a query to the data engine.

Why this lives in spec

Filter values in dashboards, views, reports and pages travel as JSON.

Because JSON cannot evaluate code, callers cannot write daysAgo(30)

inline; they use a tiny placeholder grammar instead:

{ published_at: { $gte: '{last_quarter_start}' } }

{ signal_at: { $gte: '{30_days_ago}' } }

The placeholders are expanded client-side by

resolveDateMacros() in @object-ui/core immediately before the

filter is handed to the data source. The data engine itself only

sees ISO date / timestamp strings, never \{tokens\}.

AI agents and template authors author these placeholders directly,

so the set of recognised tokens is part of the platform contract

and must live here next to the rest of the JSON-DSL schemas, not

inside any single UI implementation.

Two flavours of token

  1. Fixed tokens — small, finite list (\{today\},

\{current_quarter_start\}, \{last_year_end\}, …). Enumerated by

DATE_MACRO_TOKENS below.

  1. Parameterised tokens\{N_days_ago\}, \{N_weeks_from_now\},

etc., where N is any non-negative integer. Matched by

DATE_MACRO_PARAM_RE. Units: minute(s), hour(s), day(s),

week(s), month(s), year(s). Directions: ago, from_now.

Out of scope

  • CEL expressions (cel\daysAgo(30)``) run server-side in the

formula engine. They are unrelated to these placeholders; see

@objectstack/formula.

  • Token resolution semantics (week-start day, timezone, fiscal

calendars) are defined by the resolver implementation; spec only

freezes the vocabulary.

Source: packages/spec/src/data/date-macros.zod.ts

TypeScript Usage

import { DateMacroPlaceholder, DateMacroToken } from '@objectstack/spec/data';
import type { DateMacroPlaceholder, DateMacroToken } from '@objectstack/spec/data';

// Validate data
const result = DateMacroPlaceholder.parse(data);



On this page