Generating a Date table

Overview

When building models, you will almost always need a Date table. This is a special table where each row contains a date, and with several columns, each containing a particular value derived from each date, such as: the day name, the month, year, and so on.

Although many data sources contain a pre-built Date table, this article explains how Date tables can be generated dynamically, from scratch.

Steps

1. Create a list of dates

This query has no external data sources - all of the data returned by the query is generated in the table itself.

Create a Blank Query:

  • Click on the Get Data icon under the Data tab in Excel ➔ From Other Sources ➔ Blank Query

This will open up the Query Editor.

  • In the Formula Bar, enter the following expression as its first step:
M-Code
    = List.Dates(#date(2020,1,1), 365, #duration(1,0,0,0))

This expression uses the List.Dates() function to return a list of 365 dates starting from January 1, 2020, at increments of one day. The result should look as follows:

  • Click the ‘To Table’ button on the List tab in the Query Editor toolbar to convert the list to a table.
  • In the ‘To Table’ dialog that appears, leave the default selections of ‘None’ for the delimiter and ‘Show as errors’ for How to handle extra columns, as shown below.
  • Click OK.
  • Rename the column in the resulting table, to ‘Date’.
  • Select the ‘Date’ column in the table and convert the data type Date.

2. Create Year, Month, and Day columns

  • Select the ‘Date’ column again. Then right-click and select Duplicate Column to create a copy of the column.
  • Double-click the header of the new column and rename it ‘Year’.
  • Right-click the ‘Year’ column, then select Transform ➔ Year ➔ Year, as shown below, to replace the date values in that column with just the years.
  • Click the Custom Column button (located on the Add Column tab of the Query Editor toolbar).
  • In the window that appears enter the following code:
M-Code
    = Date.ToText([Date], "MMMM")
  • Call the new column ‘Month’
  • Click the Custom Column button again to create another new column. Call the column ‘DayName’, and enter the following code:
M-Code
    = Date.ToText([Date], "dddd")
  • Click the Custom Column button again to create another new column. Call the column ‘Week’, entering the following code:
M-Code
    = Date.WeekOfYear([Date])

The final query, showing the desired output, should now look as follows:

3. Convert into a function

The query can now also be turned into a function with two parameters, start date and end date, so that any new table containing all dates between the start date and the end date, can be generated.

The ‘M’ code below shows how to modify the query into a function, so it can be re-used on different start and end dates.

M-Code

let
DateFunction = (StartDate as date, EndDate as date) as table =>
    let
        // Find the number of dates between the start date and end date
        NumberOfDays = Duration.Days(EndDate-StartDate)+1,
        // Create a list of dates starting from the start date
        Source = List.Dates(StartDate, NumberOfDays, #duration(1,0,0,0) ),
        // Turn the list into a table
        TableFromList = Table.FromList(
                            Source,
                            Splitter.SplitByNothing(),
                            null, null,
                            ExtraValues.Error),
        // Rename the only column in the table to Date
        RenamedColumns = Table.RenameColumns(TableFromList,{{"Column1", "Date"}}),
        // Change the type of the column to Date
        ChangedType = Table.TransformColumnTypes(RenamedColumns,{{"Date", type date}}),
        // Duplicate the Date column
        DuplicatedColumn = Table.DuplicateColumn(ChangedType, "Date", "Copy of Date"),
        // Rename the duplicated column to Year
        RenamedColumns1 = Table.RenameColumns(DuplicatedColumn,{{"Copy of Date", "Year"}}),
        // Convert the dates in the Year column to years
        TransformedColumn = Table.TransformColumns(RenamedColumns1,{{"Year", Date.Year}}),
        // Add a custom column containing month names
        InsertedCustom = Table.AddColumn(TransformedColumn, "Month", each Date.ToText([Date], "MMMM")),
        // Add a custom column containing day names
        InsertedCustom1 = Table.AddColumn(InsertedCustom, "DayName", each Date.ToText([Date], "dddd")),
        // Add a custom column containing week numbers
        InsertedCustom2 = Table.AddColumn(InsertedCustom1, "Week", each Date.WeekOfYear([Date]))
    in
            InsertedCustom2
in     
    DateFunction