Docs / Build Workflow

Filter — cutoff_date

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 how date_from is derived from the chosen date. One of day, month (default), quarter, year. With day, date_from equals the chosen date (one-day window). With month, the first day of the chosen date's month. With quarter, the first day of the chosen date's calendar quarter (Jan, Apr, Jul, or Oct). With year, January 1 of the chosen date's year. Honored at both dashboard and visualization level.
  • include_current_day — boolean. Default false. 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_to sent 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 to granularity (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_date is opinionated: date_from snaps to the start of the chosen date's granularity window (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_date always emits date_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 @param placeholder 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 at today − 1. To include the in-progress day, add include_current_day: true to the filter. See Maximum selectable date.
  • The include_current_day flag 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.