Skip to main content
Calendar cubes are used to implement custom calendars, such as retail calendars. If your data model contains a calendar table, it can be modeled as a calendar cube. Calendar cubes can be used to override the default time shift behavior of time-shift measures as well as override the default granularities of time dimensions.
Calendar cubes are powered by Tesseract, the next-generation data modeling engine. In versions before v1.7.0, it was not enabled by default.

Configuration

Calendar cubes are cubes where the calendar parameter is set to true. This indicates that the cube is a calendar cube and allows the use of custom time shifts and granularities.
A calendar cube must have exactly one primary_key dimension. A second one compiles without error but makes every query that references the cube fail with Cube '...' has multiple primary keys, but only one is allowed for calendar cubes.

Joins

Calendar cubes are only useful when they are joined with other cubes in the data model.
When joining a calendar cube to other cubes, the following requirements must be met:
  • The calendar cube’s join dimension must be of type time and also be the primary_key.
  • The other cube’s join dimension must also be of type time.

Overriding time shifts

Calendar cubes can be used to override the default time shift behavior of time-shift measures. It can help implement custom time shifts or reuse common time shifts across multiple cubes. By default, a time shift like prior + 1 month will add INTERVAL '1 month' to the time dimension value in the generated SQL. However, with custom calendars, a more nuanced approach is often needed, such as mapping each date to another pre-calculated date from the calendar table. In the following example, the custom_calendar cube defines a custom time shift for prior + 1 month that uses the month_ago column from the calendar table. It also defines a custom time shift my_favorite_time_shift of type prior + the 42 days interval.
When the sales.total_sales_prior_month and sales.total_sales_few_days_ago measures are queried together with the custom_calendar.date time dimension, the generated SQL uses the custom time shifts defined in the custom_calendar cube: one with the month_ago column and another with INTERVAL '42 days'.

Overriding granularities

Calendar cubes can be used to override the default granularities of time dimensions. By default, SQL functions like DATE_TRUNC are used to calculate default granularities, such as day, month, or year. However, custom calendars often have different definitions for these periods, e.g., a retail calendar might use 4-5-4 week patterns. Calendar cubes allow you to define custom SQL expressions for each granularity. In the following example, the custom_calendar cube overrides the default month granularity with a pre-calculated mid_month column:
When querying sales.revenue by custom_calendar.date with monthly granularity, the mid_month column will be used instead of the standard DATE_TRUNC('month', date) expression in the generated SQL.
A pre-aggregation must declare the overridden granularity itself. A rollup that names it is built from the overriding column and serves those queries correctly.A rollup at a finer granularity is not a correct source. Cube can still match one through the granularity hierarchy — a day rollup for a month query — but the rollup holds DATE_TRUNC buckets that the overriding column cannot be recovered from, so the query either fails or returns Gregorian periods. Custom periods cannot be assembled from predefined ones.

Naming a granularity defined with sql

A granularity defined with sql must be named after a default granularity: second, minute, hour, day, week, month, quarter, or year. Names are matched case-insensitively. The sql parameter changes what an existing unit of time means; it cannot introduce a new one. A granularity under a name of your own, such as fiscal_week, does not compile:
The reason is that interval is what places a granularity in the dayweekmonthquarteryear hierarchy, so Cube knows what to roll it up from and what to decompose it into. A default granularity brings that position with it; a name of your own does not, so it has to state its interval. The two styles serve different purposes: Use interval to add a granularity, for example a fiscal week of a regular seven days. See the custom granularity recipe for fiscal_week, fiscal_quarter, and fiscal_year defined that way. Use sql when a period varies in length and cannot be derived arithmetically, such as the months and quarters of a 4-5-4 retail calendar. The custom calendar recipe models a 4-5-4 calendar in full.