Docs / Build Workflow

Filter — month

When to use month

Use month when the analysis is keyed on a single month — monthly close, monthly billing, comparable-month-over-comparable-month reporting. The user picks a year + month; the value is sent as a YYYY-MM string to the configured parameter.

Use a date filter (cutoff_date, date_range, date_range_preset) instead when the analysis spans an arbitrary date range rather than a calendar month.

Required fields

  • type: month

Optional fields

  • id — internal identifier.
  • label — display label above the picker.
  • param — parameter name to bind the value to. Defaults to id; if both are missing, defaults to the literal "month".
  • default — month token (see below) or ISO string in YYYY-MM format. Defaults to the current month.
  • year_min / year_max — explicit year bounds for the picker.
  • year_window, year_window_past, year_window_future — relative bounds. Defaults to a 5-year window centred on the current year.
  • month_picker — nested object that lets you override the year-bound config without polluting the top level.

Default tokens

Recognised tokens for the default field:

  • — the current calendar month in the user's timezone. Aliases: , .
  • — the calendar month before the current one (rolls back across year boundaries). Alias: .

Anything else is treated as a literal YYYY-MM string (e.g. "2024-12"). Unrecognised tokens fall through to literal parsing and silently default to the current month if malformed.

How the value reaches the Malloy query

The picker emits a YYYY-MM string on submit. Looky sets the named parameter to that string. There is no automatic expansion to date_from / date_to — if the model needs a date range, derive it inside the query from the month string.

##! experimental.parameters

source: revenue(
  p_month::string is "2024-01"
) is bigquery.table('...') extend {
  view: monthly_revenue is {
    where:
      format_datetime('%Y-%m', created_at) = p_month
    aggregate:
      revenue is sum(sale_price)
  }
}

Adapter differences

The month value is a string, not a date / timestamp parameter, so the Postgres / MySQL caveat does not apply directly. If the model casts the month string to a date inside its parameter declaration, the same caveat applies for that derived parameter — see Source adapter differences.

Worked examples

Default to the current month, 5-year window centred on this year:

filters:
  - type: month
    id: month
    label: Month
    param: month
    default: ""

Default to a literal historical month, with custom year window (3 years past, 1 year future):

filters:
  - type: month
    id: month
    label: Month
    default: "2024-12"
    year_window_past: 3
    year_window_future: 1

Frozen historical month (default fixed to a literal):

filters:
  - type: month
    label: Reporting month
    default: "2024-12"
    year_min: 2020
    year_max: 2024

Two month filters comparing periods:

filters:
  - type: month
    id: current_month
    label: Current
    param: current_month
    default: ""
  - type: month
    id: comparison_month
    label: Compare to
    param: comparison_month
    default: "2024-11"

Common pitfalls

  • The picker does not show the year you want. Set explicit year_min / year_max, or expand year_window_past / year_window_future.
  • The model expects a date, not a string. The month picker emits YYYY-MM. Either make the model parameter a string and parse it in the query, or use a date filter (date_range_preset with the this_month/last_month presets) instead.
  • Two month filters bind to the same parameter. Each must have a distinct param (or id when param is omitted), otherwise only one wins.
  • Multi-month selection is needed. Not supported by this filter — use date_range or date_range_preset.
  • Quarter or week selection is needed. Not implemented — derive these inside the model from a date filter, or pre-compute the periodicity in the underlying query.