When to use cutoff_date
Use cutoff_date when the analysis is "everything from the start of the month up to a chosen day" — month-to-date revenue, monthly closing reports, "as-of" snapshots. The user picks a single date; Looky automatically sends both date_from (the first day of that month) and date_to (the chosen date) as parameters.
Use date_range when the user needs to pick both endpoints freely. Use date_range_preset when the choice is among named presets like "last 30 days" or "this quarter".
Required fields
type: cutoff_date
Optional fields
label— display label above the picker.default— date token (see below) or ISO date string. Defaults to"".granularity— controls howdate_fromis derived from the chosen date. One ofday,month(default),quarter,year. Withday,date_fromequals the chosen date (one-day window). Withmonth, the first day of the chosen date's month. Withquarter, the first day of the chosen date's calendar quarter (Jan, Apr, Jul, or Oct). Withyear, January 1 of the chosen date's year. Honored at both dashboard and visualization level.include_current_day— boolean. Defaultfalse. See Maximum selectable date.
Maximum selectable date — today or yesterday
By default, the cutoff_date filter caps the maximum date at today − 1 day. The picker does not let the user select today, the token resolves to today but is clamped down to yesterday, and the date_to sent to the query always lands on yesterday. This is the historical convention for "as-of yesterday's close" reports: in-progress day data is usually incomplete until end-of-day, so the report anchors to the last closed day.
For live operational dashboards — where you do want to include the in-progress day — add include_current_day: true:
filters:
- type: cutoff_date
label: Cutoff
default: ""
include_current_day: true
With the flag on:
- The picker allows today as the maximum selectable date.
resolves to today and is not clamped.- The
date_tosent to the query is inclusive of the current day.
The flag is opt-in (default false) to preserve back-compat with daily-report dashboards (PDFs, period closes) whose semantics expect "through yesterday's close".
When to turn it on: live operational dashboards, "what have I accrued so far" KPIs, in-progress billing, progress monitoring. When to leave it off (default): reports exported to PDF and sent as end-of-day summaries, historical snapshots, reports that need post-close consolidation.
The flag is declared independently on each filter — on the visualization (if opened standalone) and on the dashboard (if it has a global filter that propagates via param:). If the viz lives inside a dashboard with a global filter, the dashboard flag is sufficient; the resolved value reaches the viz via the param.
Date tokens for defaults
These tokens resolve against the user's current timezone at page load:
//
Anything not in this list is treated as a literal ISO date string (e.g. "2024-12-31").
How the value reaches the Malloy query
The chosen date sets two parameters on every query that the filter applies to:
date_from— derived from the chosen date according togranularity(defaults to first day of its month).date_to— the chosen date itself.
Your Malloy model declares those two parameters and uses them in where: clauses:
##! experimental.parameters
source: orders(
p_date_from::date is @2024-01-01,
p_date_to::date is @2024-12-31
) is bigquery.table('...') extend {
view: revenue_mtd is {
where:
created_at::date >= p_date_from
and created_at::date <= p_date_to
aggregate:
revenue is sum(sale_price)
}
}
Adapter differences
Both date_from and date_to are date / timestamp parameters. On BigQuery they bind natively. On Postgres and MySQL the model must use the @param placeholder pattern in the underlying SQL — see the source adapter comparison and Malloy support.
Worked examples
Default cutoff is today:
filters:
- type: cutoff_date
label: Cutoff
default: ""
Default cutoff is end of last month (for monthly close reports):
filters:
- type: cutoff_date
label: Closing date
default: ""
Default cutoff is a literal date (for a fixed historical snapshot):
filters:
- type: cutoff_date
label: As of
default: "2024-12-31"
Common pitfalls
- The query needs a different range shape.
cutoff_dateis opinionated:date_fromsnaps to the start of the chosen date'sgranularitywindow (day, month, quarter, year). If you need the user to pick the lower bound freely, use date_range. - The Malloy model expects different parameter names.
cutoff_datealways emitsdate_from/date_to. Adapt the model parameter names accordingly, or use date_range_preset which supports custom bindings. - The query fails on Postgres or MySQL with a date-binding error. Add the
@paramplaceholder pattern in the model's SQL — see the source adapter comparison. - The default token is not recognised. Only the tokens listed above are valid. Anything else is treated as a literal date string and silently does nothing useful if it is malformed.
- Multiple cutoff_date filters in one viz. Only one cutoff applies. Use a different filter type (or two separate parameter pairs) if you need multiple time windows.
- "The report only shows up to yesterday even though I set
". That is the default behaviour — the cutoff caps attoday − 1. To include the in-progress day, addinclude_current_day: trueto the filter. See Maximum selectable date. - The
include_current_dayflag is on the viz but the dashboard still shows yesterday. When the viz lives inside a dashboard with a global filter (param: cutoff_date), it is the dashboard's filter flag that wins — the dashboard resolves the value and propagates it to the viz via the param. Turn the flag on at the dashboard filter, not just at the viz.