Building a Date Dimension Table
IntermediateGenerate a complete date table in M with year, month, quarter, week, and fiscal period columns — no external data source needed.
Why Build a Date Table in M?
A date dimension table is essential for time intelligence in Power BI and Excel. Building it in M — rather than importing from a spreadsheet or database — means it regenerates automatically, stays in sync with your data, and requires no external dependencies.
The Core Pattern
Generate a list of dates, then transform each date into a record with all the columns you need:
let
StartDate = #date(2020, 1, 1),
EndDate = #date(2030, 12, 31),
DayCount = Duration.Days(EndDate - StartDate) + 1,
DateList = List.Transform(
List.Generate(() => 0, each _ < DayCount, each _ + 1),
each Date.AddDays(StartDate, _)
),
DateTable = Table.FromList(DateList, Splitter.SplitByNothing(), {"Date"}),
Typed = Table.TransformColumnTypes(DateTable, {{"Date", type date}}),
WithColumns = Table.AddColumn(Typed, "Year", each Date.Year([Date]), Int64.Type),
WithMonth = Table.AddColumn(WithColumns, "Month", each Date.Month([Date]), Int64.Type),
WithMonthName = Table.AddColumn(WithMonth, "MonthName", each Date.MonthName([Date]), type text),
WithDay = Table.AddColumn(WithMonthName, "Day", each Date.Day([Date]), Int64.Type),
WithQuarter = Table.AddColumn(WithDay, "Quarter",
each "Q" & Text.From(Number.RoundUp(Date.Month([Date]) / 3)), type text),
WithWeek = Table.AddColumn(WithQuarter, "WeekOfYear",
each Date.WeekOfYear([Date]), Int64.Type),
WithDayOfWeek = Table.AddColumn(WithWeek, "DayOfWeek",
each Date.DayOfWeekName([Date]), type text),
WithIsWeekend = Table.AddColumn(WithDayOfWeek, "IsWeekend",
each Date.DayOfWeek([Date]) >= 5, type logical),
WithYearMonth = Table.AddColumn(WithIsWeekend, "YearMonth",
each Date.Year([Date]) * 100 + Date.Month([Date]), Int64.Type)
in
WithYearMonthMaking the Date Range Dynamic
Drive the start and end dates from your actual data so the table always covers exactly what's needed:
let
// Reference your fact table
FactTable = Sales,
MinDate = List.Min(Table.Column(FactTable, "OrderDate")),
MaxDate = List.Max(Table.Column(FactTable, "OrderDate")),
// Add a buffer so future dates are included
StartDate = Date.StartOfYear(MinDate),
EndDate = Date.EndOfYear(Date.AddYears(MaxDate, 1)),
DayCount = Duration.Days(EndDate - StartDate) + 1,
DateList = List.Transform(
List.Generate(() => 0, each _ < DayCount, each _ + 1),
each Date.AddDays(StartDate, _)
)
in
DateListAdding Fiscal Periods
If your fiscal year starts in a month other than January (e.g., July = month 7):
let
FiscalYearStartMonth = 7,
WithFiscalYear = Table.AddColumn(DateTable, "FiscalYear",
each
if Date.Month([Date]) >= FiscalYearStartMonth
then Date.Year([Date]) + 1
else Date.Year([Date]),
Int64.Type),
WithFiscalMonth = Table.AddColumn(WithFiscalYear, "FiscalMonth",
each
let m = Date.Month([Date]) - FiscalYearStartMonth + 1
in if m <= 0 then m + 12 else m,
Int64.Type),
WithFiscalQuarter = Table.AddColumn(WithFiscalMonth, "FiscalQuarter",
each "Q" & Text.From(Number.RoundUp([FiscalMonth] / 3)),
type text)
in
WithFiscalQuarterPerformance Tip
Mark the Date column as the primary key and set the table to not summarize in Power BI. Buffer the table if other queries reference it repeatedly:
Result = Table.Buffer(WithFiscalQuarter)This prevents M from regenerating the full date list every time another query joins against it.