Skip to main content
This recipe explains the implementation of the 4-5-4 calendar, a common retail calendar used in the US and Canada. However, the same approach can be used to implement other custom calendars. Unlike custom time dimension granularities, custom calendars provide more flexibility and can be used when time units have variable lengths, such as the months and quarters in the 4-5-4 calendar. See the custom granularities recipe for more information.

Use case

The 4-5-4 calendar ensures sales comparability between years by dividing the year into months based on a 4 weeks – 5 weeks – 4 weeks format. The layout of the calendar lines up holidays and ensures the same number of Saturdays and Sundays in comparable months. Hence, like days are compared to like days for sales reporting purposes.

Data modeling

The data modeling includes the following steps:
  • Create a calendar cube, e.g., calendar_454.
  • Extend it a number of times, so there’s one calendar cube for every time dimension in cubes with facts that needs translation to a custom calendar.
  • Define joins from your cubes with facts to those calendar cubes, e.g., base_orders, and bring relevant calendar attributes as proxy dimensions.
The last two steps require a few lines of code but it can totally be optimized with a Jinja macro if needed.

Calendar table

Consider the following calendar cube. It was generated using a large language model (LLM) and then tested against the official calendar. In this example, it’s generated on the fly, however, in production, it should be materialized as a table using a data transformation tool:
As you can see, this cube defines week_start_date and week_end_date time dimensions as the start and end dates of the retail week. They can be used to join this cube to cubes with facts.

Auxiliary calendar cubes

We will also extend the calendar_454 cube to create auxiliary calendar cubes for three time dimensions that we’d like to translate to the 4-5-4 calendar:

Cubes with facts

Finally, we define joins from the base_orders cube to the auxiliary calendar cubes. We also bring the week_number and month_number attributes as proxy dimensions: