A recent question from one of our Power Query Academy registrants was about creating a fiscal Saturday calendar - or a calendar where periods end on the last Saturday of each month. I cooked up a sample of one way to approach this task, but I'm curious if anyone out there has something better.
Basic Goal of the Fiscal Saturday Calendar
The basic goal here is to create a full calendar table with three columns:
- A primary "Date" column which holds a single value for every day of the period
- A "Fiscal ME" column that holds the fiscal month end based on the final Saturday of the month
- A "Fiscal YE" column that holds the fiscal year end based on the last Saturday of the year
The trick here is that, unlike a 4-4-5 calendar which has consistent repeating pattern, the number of weeks per month end could shift unpredictably - especially when you take into account leap years.
Starting with the basic Calendar framework
I started as I usually do with a Calendar table, by following my standard calendar pattern from our Power Query Recipe Card set. I busted out pattern 60.100 to build both the calendar StartDate and EndDate, leaving me two queries with the appropriate values:
And from there, using recipe card 60.105, I expanded this into a full blown calendar with every day from StartDate to EndDate:
I named this table Calendar-Base and loaded it as a Staging (or Connection only) Query (covered in recipe card 0.110).
The only real thing to note here is that my StartDate and EndDate are the first day of the first fiscal year (a Sunday), and the EndDate is the end of the next year (a Saturday that is 768 days later.)
Creating Fiscal Month and Year ends for the Fiscal Saturday Calendar
The next step was to create a table that generated the fiscal month ends and fiscal years ends for the calendar. So I create a new query that referenced the Calendar-Base query.
To ensure it was a fiscal Saturday calendar, the dates needed to be based on the last Saturday of the month and last Saturday of the year. And in order to work these out, I needed two columns: DayID and DayOfWeek. To create these:
- DayID: I added an Index Column starting from 1. This generates a unique DayID for every row of the table
- DayOfWeek: I selected the Date column --> Add Column --> Date --> Day of Week
With these in place, I was now set to create the Month End and Year End columns as follows:
- Add Column --> Custom Column
- Name: Fiscal ME
- Formula:
=if Duration.Days( Duration.From(Date.EndOfMonth([Date]) - [Date])) <7 and [Day of Week] = 6 then [Date] else null
- Add Column --> Custom Column
- Name: Fiscal ME
- Formula:
=if Number.Mod([DayID],364)=0 then [Date] else null
These formulas flagged the fiscal Saturday calendar periods as shown here:
The final steps to this stage were then to:
- Filter all the nulls out of the FiscalME column
- Remove all but the FiscalME and FiscalYE columns
- Fill the FiscalYE column up
- Set the data types on both columns to Date
- Name the table "Calendar-FiscalPeriods"
- Load as a Staging query (recipe card 0.110 again)
At the end of the process, the calendar clearly shows our fiscal Saturday calendar period ends:
Finishing the Fiscal Saturday Calendar
The final step is now to put these together. The way I approached this was:
- Create a new query that references the Calendar-Base table
- Merge the Calendar-Fiscal Periods to get an Exact Match between the Date and Fiscal ME columns (recipe card 30.105)
- Expand the Fiscal ME and Fiscal YE columns
- Fill the Fiscal ME and Fiscal YE columns up
- Name the query Calendar
- Load it to the desired destination
Now, to be fair, the calendar only looks like this at this point:
I could certainly add other components. For a Fiscal Year column, I just need to select Fiscal YE and add a date column. For months, I'd add a month based on the Fiscal ME column. And may other patterns can be applied based on the standard date transforms.
And one caveat... the dates fed in must start on the first day of a fiscal, and end on the last day of a fiscal to ensure it works correctly.
My sample file can be found here.
Do you have an easier way?
So here comes the thrust of this... I have easy patterns for standard 12 month calendars, 4-4-5 and their variants and even 13 weeks per year. But this one, with it's shifting weeks per month threw me off a bit. I'm curious if anyone has an easier way to generate this which wouldn't rely on splitting this out into separate tables.
3 thoughts on “Creating a Fiscal Saturday Calendar”
Maybe not easier but without limits for StartDate and EndDate. (so, StartDate and EndDate are any)
1. Calendar-Base_BS
let
Source = Table.FromColumns({{Number.From(StartDate)..Number.From(Date.AddMonths(EndDate, 1))}}, {"Date"}),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}})
in
#"Changed Type"
2. Calender-FiscalPeriods_BS
let
Source = Table.FromColumns({{Date.AddMonths(Date.EndOfMonth(StartDate),-1) } & List.Generate(() => [Start = Date.EndOfMonth(StartDate), i=1, MY = Start],
each Date.AddMonths([Start], [i]-1) <= Date.EndOfMonth(Date.AddMonths(EndDate, 1)),
each [MY = Date.AddMonths([Start], [i]), i = [i]+1, Start = [Start]],
each [MY])}),
LastSatInMonth = Table.AddColumn(Source, "Fiscal ME", each [Column1] - #duration(Date.DayOfWeek([Column1], Day.Saturday), 0, 0, 0), type date),
#"Inserted End of Year" = Table.AddColumn(LastSatInMonth, "End of Year", each Date.EndOfYear([Fiscal ME]), type date),
#"Inserted Day of Week" = Table.AddColumn(#"Inserted End of Year", "Dzie? tygodnia", each Date.DayOfWeek([End of Year], Day.Saturday), Int64.Type),
#"Added Custom" = Table.AddColumn(#"Inserted Day of Week", "Fiscal YE", each [End of Year] - #duration([Dzie? tygodnia],0,0,0), type date),
#"Removed Other Columns" = Table.SelectColumns(#"Added Custom",{"Fiscal ME", "Fiscal YE"})
in
#"Removed Other Columns"
3. Calendar_BS (Merge)
let
Source = Table.NestedJoin(#"Calendar-Base_BS", {"Date"}, #"Calender-FiscalPeriods_BS", {"Fiscal ME"}, "Tbl", JoinKind.LeftOuter),
#"Expanded {0}" = Table.ExpandTableColumn(Source, "Tbl", {"Fiscal ME", "Fiscal YE"}),
#"Sorted Rows1" = Table.Sort(#"Expanded {0}",{{"Date", Order.Ascending}}),
#"Filled Up" = Table.FillUp(#"Sorted Rows1",{"Fiscal ME", "Fiscal YE"}),
#"Filtered Rows" = Table.SelectRows(#"Filled Up", each [Date] <= EndDate)
in
#"Filtered Rows"
Cheers :-))
Pingback: Power BI Paginated, DAX, Power Query and more... (April 22, 2019) | Guy in a Cube
Hi Ken,
Thank you for the interesting challenge for a Power Query weekender like myself. I have started playing around and putting together the code below. I know that this is not exactly what you have done for Fiscal Year Saturday. But just thought to share this with you and your readers.
let
start_date = #date(2018, 12, 30),
end_date = #date(2020, 12, 26),
dates = List.Generate(
() => start_date,
each _ = start_date and [Date] <= end_date
),
add_year_end = Table.AddColumn(
select_dates,
"Is Year End",
each Text.EndsWith([Yr_Mo], "-12") and [EOM] = [Date]
),
change_column_type = Table.TransformColumnTypes(
add_year_end,
{
{ "Date", type date },
{ "Is Year End", type logical }
}
)
in
change_column_type