modellerUpdated 2026-08-21

Configure Calendar Table

What this covers

A calendar table holds one row per date with pre-computed period columns — year, quarter, month, week, day. Period-aware time variants (_ytd, _prior_year, _yoy_growth, ...) can use calendar table columns for period boundaries when the table is present.

A calendar table is not required for most time variants. Tessallite computes standard, fiscal, ISO Week, and Thai Buddhist period boundaries from SQL expressions derived from the hierarchy calendar type. Physical calendar tables are required only for table-bound calendars and explicit physical-table workflows:

Tessallite supports six calendar types: Standard (Gregorian), Fiscal, ISO Week, Retail 4-4-5, Hijri (Islamic), and Thai Buddhist. A single model can use multiple calendar types, for example fiscal for finance and 4-4-5 for retail reporting. A physical table is only needed when the calendar type or modelling workflow requires one. See Calendar Types for when to use each type.

This article explains how to create, bind, and manage calendar tables.

Calendar table requirement rule

Use a physical calendar table only when the calendar or workflow needs one. Standard, fiscal, ISO Week, and Thai Buddhist time variants can use the calendar type on the time hierarchy without a bound table. Retail 4-4-5 and Hijri time variants need a bound physical calendar table. Dense date enumeration, custom business period columns, coverage checks, and calendar dimension aliases also need a bound table because those workflows join to or inspect real calendar rows.

When you bind an existing table, map the real source columns. Do not keep default names such as date_key or year_no unless those columns actually exist in the source.

Before you start

Standard column shape

PeriodColumn name
Datedate_key
Yearyear_no
Year captionyear_label (generated calendar tables; caption-only)
Halfhalf_no
Quarterquarter_no
Monthmonth_no
Weekweek_no
Day of yearday_no

date_key is the only required column. Period columns are optional but a variant that needs a missing period column will be silently dropped from the catalog.

Standard generated calendars also include year_label, with the same plain integer value as year_no; the tenant format only changes captions for fiscal and NRF retail years that span two calendar years.

Fiscal and retail year captions

Fiscal and NRF retail calendars emit a caption-only year_label beside the numeric year_no/retail_year key. Choose the tenant-wide convention with calendar.fiscal_year_label_format through GET/PUT /api/v1/tenants/{tenant_id}/calendar-settings:

TokenExample for a year starting in February
start_year (default)2025
span_short2025-26
span_long2025-2026
span_fyFY25-26
end_yearFY2026

The numeric year remains the key, sort, and join field. January-start fiscal calendars and ISO week calendars always use the plain integer. Existing source tables need a normal calendar rebuild before year_label is available; until then Excel, Power BI, and XMLA metadata deliberately fall back to the numeric key. Unknown tokens are rejected with HTTP 422.

Choosing the right calendar type

TypeUse whenFiscal start month
StandardReporting follows the common Gregorian calendarn/a
FiscalFinancial year starts on a month other than JanuaryRequired
ISO WeekYou need ISO 8601 week numbering (logistics, EU reporting)n/a
Retail 4-4-5Retail or CPG like-for-like weekly comparisonsn/a
HijriIslamic finance or Middle Eastern government reportingn/a
Thai BuddhistThai government or financial institutionsn/a

Select the type in the Calendar type dropdown when creating or binding a calendar. The type determines which period columns the DDL generates and how period boundaries are computed.

Steps — auto-create

  1. Open the Sources panel in Model Builder.
  2. On the data source row, click the calendar icon. The icon shows blue once a calendar is bound.
  3. Switch to the Auto-create tab.
  4. Select the Calendar type from the dropdown.
  5. If Fiscal is selected, set the Fiscal year start month (e.g. April).
  6. Set Table name (e.g. calendar_fiscal). Enter the table name only — Tessallite qualifies it automatically using the source's schema or dataset configuration:
  1. Choose a start date and end date for the calendar range. Best practice: cover 5 years past and 3 years future to avoid NULL period values on edge dates.
  2. Click Generate. Tessallite emits the dialect-specific DDL (Postgres generate_series, BigQuery GENERATE_DATE_ARRAY, or Spark sequence/explode) and runs it against the source. The new table is registered with autocreated = true and bound automatically. A companion model table alias is created so the calendar participates in joins and time-variant measures.

Auto-create requires write access

The Generate button only runs DDL when the project connection has "Allow Tessallite to run DDL on this source" enabled. This is a deliberate opt-in so Tessallite can never write to a source the operator hasn't explicitly approved. If the flag is off, Generate returns the DDL in the error payload and asks you to use the script + bind path.

To enable the flag: open Connections, edit the connection, and check the "Allow Tessallite to run DDL on this source" checkbox under the connection settings. For BigQuery, the service account also needs the BigQuery Data Editor role (or higher) on the target dataset.

Steps — bind an existing table

  1. Open Sources → Calendar as above.
  2. Click Bind existing.
  3. Enter the table name (schema-qualified if required by your source).
  4. Confirm the column mapping. Tessallite probes the table for the standard column names; if any are missing or use different names, edit the mapping inline.
  5. Click Bind. The catalog refreshes; period-aware variants on measures linked to this source's hierarchy now become admissible.

Unbinding

Click Unbind in the Calendar panel. This removes the registration only — the physical table on the source is never dropped, even if Tessallite created it.

Script-only mode

If your security policy disallows write access from Tessallite, switch to the Get script tab, click Show DDL, copy the output, and run it on your source. Then come back, switch to Bind existing, and bind the table. Same outcome as auto-create, with you in control of the write.

Using the calendar in the model

Period-aware time variants no longer require a calendar table. Setting a calendar type on the time hierarchy is sufficient — Tessallite derives period boundaries from SQL expressions. See Configure Time Variants for the full setup.

When a calendar table IS bound, Tessallite uses its pre-computed columns instead of expression-based boundaries for backward compatibility. This is automatic — the query router detects the calendar table and switches to the column-based path.

A calendar table adds value in these scenarios:

  1. Retail 4-4-5 periods — the irregular 4-week/5-week pattern cannot be expressed as date arithmetic. You must bind a 4-4-5 calendar table for retail period variants to work.
  2. Dense date spine — queries that need every date in a range (including dates with no fact rows) use the calendar table as a dense join source.
  3. Custom period columns — if your organisation uses non-standard period definitions (e.g. 13-period years, company-specific fiscal quarters), store them as columns in a calendar table.

Check calendar coverage

Use Check calendar coverage to confirm the calendar actually spans your fact data before you rely on period rollups. The check compares the calendar's date range against the range of dates present in the fact table.

This matters because of a quiet failure mode: if some fact dates fall outside the calendar — for example the fact table has 2026 rows but the calendar only goes to 2025 — those rows get NULL period values and drop silently out of period rollups. Your year-to-date and monthly totals would simply under-count, with no error to warn you. The coverage check turns that silent gap into a clear message: it reports the exact fact range and calendar range so you can see the shortfall and extend the calendar to cover it. A green result means every fact date is covered.

Run this whenever you load new fact data, change the calendar's range, or notice a period total looking lower than you expected.

Troubleshooting

Best practices

Pitfalls

Related