Forum Discussion
jaryszek
Super User
1 year agoHow to handle 53th week 445 calendar
Hi Guys, I am try to use this code: https://gorilla.bi/power-query/445-calendar/ let
// ===== USER PARAMETERS =====
StartDate = #date(2024, 1, 29), // Enter your fiscal calenda...
- 1 year ago
pls try
let // ===== USER PARAMETERS ===== StartDate = #date(2024, 1, 29), // Enter your fiscal calendar start date EndDate = #date(2030, 1, 25), // Enter your fiscal calendar end date Order445 = {4, 4, 5}, // Pattern for months in quarter: 4-4-5 // ===== 53RD WEEK LOGIC ===== // Function to determine if a fiscal year needs 53 weeks Needs53Weeks = (fiscalYearStart as date) as logical => let // Method 1: Check if fiscal year start falls on Thursday, Friday, or Saturday startDayOfWeek = Date.DayOfWeek(fiscalYearStart, Day.Monday), // 0=Monday, 6=Sunday needsExtra = startDayOfWeek >= 3 and startDayOfWeek <= 5 // Thu, Fri, Sat in needsExtra, // Alternative method: Check if adding 364 days overshoots the next fiscal year start // This is more accurate for custom fiscal calendars Needs53WeeksAlt = (fiscalYearStart as date, nextFiscalYearStart as date) as logical => let standardYearEnd = Date.AddDays(fiscalYearStart, 363), // 364 days - 1 daysBetween = Duration.Days(nextFiscalYearStart - fiscalYearStart), needsExtra = daysBetween > 364 in needsExtra, // ===== CREATE BASE DATE LIST ===== Dates = List.Dates(StartDate, Duration.Days(EndDate-StartDate)+1, #duration(1,0,0,0)), Source = Table.FromList(Dates, Splitter.SplitByNothing(), {"Date"}), AddDayIndex = Table.AddIndexColumn(Source, "DayIndex", 0, 1, Int64.Type), // ===== FISCAL YEAR CALCULATION WITH 53RD WEEK ===== BaseDaysInYear = List.Sum(Order445) * 4 * 7, // 364 days DaysInQuarter = List.Sum(Order445) * 7, // 91 days // Determine fiscal year boundaries considering 53rd week AddFiscalYearInfo = Table.AddColumn(AddDayIndex, "FiscalYearInfo", (row) => let currentDate = row[Date], yearsSinceStart = Number.IntegerDivide(row[DayIndex], BaseDaysInYear), // Calculate this fiscal year's start baseYearStart = Date.AddDays(StartDate, yearsSinceStart * BaseDaysInYear), // Check if this fiscal year needs 53 weeks needs53 = Needs53Weeks(baseYearStart), actualDaysInYear = if needs53 then BaseDaysInYear + 7 else BaseDaysInYear, // Recalculate year index with variable year lengths adjustedYearIndex = let totalDays = 0, yearIndex = 1, findYear = List.Generate( () => [year = 1, cumulativeDays = 0], each [cumulativeDays] <= row[DayIndex], each let yearStart = Date.AddDays(StartDate, [cumulativeDays]), yearNeeds53 = Needs53Weeks(yearStart), yearDays = if yearNeeds53 then BaseDaysInYear + 7 else BaseDaysInYear in [year = [year] + 1, cumulativeDays = [cumulativeDays] + yearDays] ), lastItem = List.Last(findYear) in lastItem[year] - 1, fiscalYear = Date.Year(StartDate) + adjustedYearIndex - 1 in [ YearIndex = adjustedYearIndex, FiscalYear = fiscalYear, Has53Weeks = needs53, DaysInThisYear = actualDaysInYear ], type record ), // Extract fiscal year info AddYearIndex = Table.AddColumn(AddFiscalYearInfo, "YearIndex", each [FiscalYearInfo][YearIndex], Int64.Type), AddFiscalYear = Table.AddColumn(AddYearIndex, "FiscalYear", each [FiscalYearInfo][FiscalYear], Int64.Type), AddHas53Weeks = Table.AddColumn(AddFiscalYear, "Has53Weeks", each [FiscalYearInfo][Has53Weeks], Logical.Type), AddDaysInYear = Table.AddColumn(AddHas53Weeks, "DaysInThisYear", each [FiscalYearInfo][DaysInThisYear], Int64.Type), // Calculate day of fiscal year (1-364 or 1-371) AddDayOfYear = Table.AddColumn(AddDaysInYear, "DayOfYear", (row) => let // Find the start of this fiscal year yearStartDayIndex = let findStart = List.Generate( () => [year = 1, cumulativeDays = 0], each [year] < row[YearIndex], each let yearStart = Date.AddDays(StartDate, [cumulativeDays]), yearNeeds53 = Needs53Weeks(yearStart), yearDays = if yearNeeds53 then BaseDaysInYear + 7 else BaseDaysInYear in [year = [year] + 1, cumulativeDays = [cumulativeDays] + yearDays] ), result = if List.Count(findStart) = 0 then 0 else List.Last(findStart)[cumulativeDays] in result, dayOfYear = row[DayIndex] - yearStartDayIndex + 1 in dayOfYear, Int64.Type ), // ===== QUARTER AND PERIOD CALCULATION ===== AddQuarterInfo = Table.AddColumn(AddDayOfYear, "QuarterInfo", (row) => let dayOfYear = row[DayOfYear], has53Weeks = row[Has53Weeks], // Standard quarter calculation quarterIndex = Number.IntegerDivide(dayOfYear-1, DaysInQuarter) + 1, dayOfQuarter = Number.Mod(dayOfYear-1, DaysInQuarter) + 1, // Adjust for 53rd week (add to Q4) adjustedQuarter = if has53Weeks and dayOfYear > (DaysInQuarter * 3) then [ QuarterIndex = 4, DayOfQuarter = dayOfYear - (DaysInQuarter * 3), DaysInThisQuarter = DaysInQuarter + 7 // Q4 gets extra week ] else if quarterIndex > 4 then // Safety check [ QuarterIndex = 4, DayOfQuarter = dayOfQuarter + DaysInQuarter, DaysInThisQuarter = DaysInQuarter + 7 ] else [ QuarterIndex = quarterIndex, DayOfQuarter = dayOfQuarter, DaysInThisQuarter = if quarterIndex = 4 and has53Weeks then DaysInQuarter + 7 else DaysInQuarter ] in adjustedQuarter, type record ), AddQuarterIndex = Table.AddColumn(AddQuarterInfo, "QuarterIndex", each [QuarterInfo][QuarterIndex], Int64.Type), AddDayOfQuarter = Table.AddColumn(AddQuarterIndex, "DayOfQuarter", each [QuarterInfo][DayOfQuarter], Int64.Type), AddDaysInQuarter = Table.AddColumn(AddDayOfQuarter, "DaysInThisQuarter", each [QuarterInfo][DaysInThisQuarter], Int64.Type), // ===== PERIOD CALCULATION WITH 53RD WEEK ===== AddPeriodInfo = Table.AddColumn(AddDaysInQuarter, "PeriodInfo", (row) => let dayOfQuarter = row[DayOfQuarter], quarterIndex = row[QuarterIndex], has53Weeks = row[Has53Weeks], order = Order445, // Calculate period within quarter periodOfQuarter = if dayOfQuarter <= order{0} * 7 then 1 else if dayOfQuarter <= (order{0} + order{1}) * 7 then 2 else 3, // For 53rd week: add to last period of last quarter (Period 12) isLastPeriodWith53 = quarterIndex = 4 and periodOfQuarter = 3 and has53Weeks, // Calculate days in this period daysInPeriod = let standardDays = order{periodOfQuarter-1} * 7 in if isLastPeriodWith53 then standardDays + 7 else standardDays, // Calculate day of period dayOfPeriod = let offset = if periodOfQuarter = 1 then 0 else if periodOfQuarter = 2 then order{0} * 7 else (order{0} + order{1}) * 7 in dayOfQuarter - offset, // Period number in fiscal year periodOfYear = (quarterIndex - 1) * 3 + periodOfQuarter in [ PeriodOfQuarter = periodOfQuarter, Period = periodOfYear, DayOfPeriod = dayOfPeriod, DaysInPeriod = daysInPeriod, IsLeapPeriod = isLastPeriodWith53 ], type record ), AddPeriodOfQuarter = Table.AddColumn(AddPeriodInfo, "PeriodOfQuarter", each [PeriodInfo][PeriodOfQuarter], Int64.Type), AddPeriod = Table.AddColumn(AddPeriodOfQuarter, "Period", each [PeriodInfo][Period], Int64.Type), AddDayOfPeriod = Table.AddColumn(AddPeriod, "DayOfPeriod", each [PeriodInfo][DayOfPeriod], Int64.Type), AddDaysInPeriod = Table.AddColumn(AddDayOfPeriod, "DaysInPeriod", each [PeriodInfo][DaysInPeriod], Int64.Type), AddIsLeapPeriod = Table.AddColumn(AddDaysInPeriod, "IsLeapPeriod", each [PeriodInfo][IsLeapPeriod], Logical.Type), // ===== WEEK CALCULATIONS ===== AddWeekIndex = Table.AddColumn(AddIsLeapPeriod, "WeekIndex", each Number.IntegerDivide([DayOfYear]-1, 7) + 1, Int64.Type), AddWeekOfQuarter = Table.AddColumn(AddWeekIndex, "WeekOfQuarter", each Number.Mod([WeekIndex]-1, if [Has53Weeks] and [QuarterIndex] = 4 then 14 else 13) + 1, Int64.Type), AddWeekOfPeriod = Table.AddColumn(AddWeekOfQuarter, "WeekOfPeriod", each Number.IntegerDivide([DayOfPeriod]-1, 7) + 1, Int64.Type), // ===== LABELS ===== AddQuarterLabel = Table.AddColumn(AddWeekOfPeriod, "QuarterLabel", each "Q" & Text.From([QuarterIndex])), AddPeriodLabel = Table.AddColumn(AddQuarterLabel, "PeriodLabel", each "P" & Text.PadStart(Text.From([Period]),2,"0")), AddWeekLabel = Table.AddColumn(AddPeriodLabel, "WeekLabel", each "W" & Text.PadStart(Text.From([WeekIndex]),2,"0")), // ===== DATE RANGES ===== // Week Start and End (assuming weeks start on Monday) AddWeekStart = Table.AddColumn(AddWeekLabel, "WeekStart", each Date.AddDays([Date], -Number.Mod(Date.DayOfWeek([Date], Day.Monday), 7))), AddWeekEnd = Table.AddColumn(AddWeekStart, "WeekEnd", each Date.AddDays([WeekStart], 6)), // Fiscal Year Start and End AddYearStart = Table.AddColumn(AddWeekEnd, "YearStart", each Date.AddDays([Date], -([DayOfYear]-1))), AddYearEnd = Table.AddColumn(AddYearStart, "YearEnd", each Date.AddDays([YearStart], [DaysInThisYear]-1)), // Fiscal Quarter Start and End AddQuarterStart = Table.AddColumn(AddYearEnd, "QuarterStart", each Date.AddDays([Date], -([DayOfQuarter]-1))), AddQuarterEnd = Table.AddColumn(AddQuarterStart, "QuarterEnd", each Date.AddDays([QuarterStart], [DaysInThisQuarter]-1)), // Period Start and End AddPeriodStart = Table.AddColumn(AddQuarterEnd, "PeriodStart", each Date.AddDays([Date], -([DayOfPeriod]-1))), AddPeriodEnd = Table.AddColumn(AddPeriodStart, "PeriodEnd", each Date.AddDays([PeriodStart], [DaysInPeriod]-1)), // Clean up and reorder columns RemoveHelperColumns = Table.RemoveColumns(AddPeriodEnd, {"DayIndex", "FiscalYearInfo", "QuarterInfo", "PeriodInfo"}), FinalTable = Table.SelectColumns( RemoveHelperColumns, { "Date", "FiscalYear", "YearStart", "YearEnd", "Has53Weeks", "DaysInThisYear", "QuarterIndex", "QuarterLabel", "QuarterStart", "QuarterEnd", "DaysInThisQuarter", "Period", "PeriodLabel", "PeriodStart", "PeriodEnd", "DaysInPeriod", "IsLeapPeriod", "WeekIndex", "WeekLabel", "WeekOfQuarter", "WeekOfPeriod", "WeekStart", "WeekEnd", "DayOfYear", "DayOfQuarter", "DayOfPeriod" } ) in FinalTable - 1 year ago
Calendars are immutable. There is no point trying to do this in Power Query or DAX. Use an external precomputed reference table.