Skip to main content
Announcements
Qlik Connect 2024! Seize endless possibilities! LEARN MORE
cancel
Showing results for 
Search instead for 
Did you mean: 
farheenayesha
Creator
Creator

Calculating Nth day of Quarter & Year by excluding holidays and weekends

Hi,

I am trying to calculate Nth day of fiscal Quarter and Year for current and previous year using Invoice date by excluding hoildays and weekends. I want to create two fields as 'Nth Day by Qtr_PY ', 'Nth Day by Qtr_CY','Nth Day by Yr_CY' and 'Nth Day by Yr_PY',. Please find the data and holiday list attached. Help me to get the output similar to the output sheet in the attached excel.

2 Solutions

Accepted Solutions
sunny_talwar

Changed the def. of the flags a little bit... check this

WeekBased445:
LOAD *,
	 If(MonthStart = Previous(MonthStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Month_CY'), 1), Peek('Nth Day by Month_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Month_CY],
	 If(QuarterStart = Previous(QuarterStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Qtr_CY'), 1), Peek('Nth Day by Qtr_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Qtr_CY],
	 If(YearStart = Previous(YearStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Yr_CY'), 1), Peek('Nth Day by Yr_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Yr_CY];

View solution in original post

sunny_talwar


@farheenayesha wrote:

Thanks for the reply Sunny. The new code is working fine for Month but showing the same values as Month for QTR and Year.  I am trying to understand your code. Meanwhile could you please help me to resolve Qtr and Year.


Are you not seeing this?

image.png

I am seeing 0 for Qtr and Yr on 1/2/2017.... Is this not what you want? or the issue is elsewhere? You will have to provide more details as to what is not working for Qtr and Yr?

View solution in original post

11 Replies
sunny_talwar

Now Quarter seems to be behave differently compared to Months. They spill over to next quarter?

image.png

farheenayesha
Creator
Creator
Author

Actually the logic is same as month Sunny. 

Let me explain you the logic:

We follow 4,4,5 weeks logic for the months. 

MonthNo. of Weeks
Jan4
Feb4
Mar5
Apr4
May4
Jun5
Jul4
Aug4
Sep5
Oct4
Nov4
Dec5

 

If a month's 1st day falls on 5th or 4th week of any month, then will check if the month is having 4 weeks or 5 weeks. According to the no.of weeks the month will start from the previous month or the next month. 

Ex.  In your snapshot. Since Mar is 5week's month and 1st  and 2nd Apr is falling on the 5th week of Mar, hence 1st and 2nd Apr is considered as part of Mar month.  Hence this is considered as part of 1st quarter. 

The below snapshot is for the Nth day of Month. Even here the 1st and 2nd Apr is part of Mar month and Apr is starting from the 3rd.

Capture2.JPG

 

 

Please let me know if you need more clarifications.

 

sunny_talwar

I think in that case you need to start with a master calendar based on the following idea

Recipe for a 4-4-5 Calendar (Script: Calendars Script)

Once you have this in place, it will be very simple to create a count like the one you want.

sunny_talwar

Sharing the script using the link from HIC's blog

Holiday:
Mapping
LOAD Holidays,
	 1
FROM
[..\..\Downloads\Dummy data.xlsx]
(ooxml, embedded labels, table is [Holiday List]);

Data:
LOAD [Invoice Date]
FROM
[..\..\Downloads\Dummy data.xlsx]
(ooxml, embedded labels, table is Data);

// ========= Fast method, using symbol tables ===================================================================
MinMaxDate:
Load
	Num(YearStart(Min(Fieldvalue('Invoice Date',RecNo())))) 		as MinDate,  
	Num(Max(Fieldvalue('Invoice Date',RecNo()))) 		as MaxDate  
Autogenerate FieldValueCount('Invoice Date'); 

Let vMinDate = Peek('MinDate',0,'MinMaxDate');
Let vMaxDate = Peek('MaxDate',0,'MinMaxDate');

Drop Table MinMaxDate;

// ==============================================================================================================
// === Step 3a: Explanation of the used parameters                                                            ===
// ==============================================================================================================

// ==============================================================================================================
// ===  The First Month Of The Year =============================================================================
// This variable defines on which month the fiscal year starts. It is used only for the month-based fiscal 
// calendar.

SET vCal_FM 		= 1; 	// First Month of the year {1=Jan, 2=Feb, ... , 12=Dec}

// ==============================================================================================================
// === Step 3b: Generate Week-based 4-4-5 Calendar                                                            ===
// ==============================================================================================================

Set vCal_FD 		= 1; 	// First Day of the week {0=Mon, 1=Tue, ... , 6=Sun}
Set vCal_RD 		= 5; 	// Reference day = The day that always belong to week one

// --- Calculate Start date -------------------------------------------------------------------------------------
Let vWeekStart 		= WeekStart(vMinDate-vCal_FD)+vCal_FD;
Let vRefDate		= YearStart(vWeekStart-vCal_RD+7)+vCal_RD-1;
Let vStartDate 		= WeekStart(vRefDate-vCal_FD)+vCal_FD-1;

// --- Calculate End date ---------------------------------------------------------------------------------------
Let vWeekStart 		= WeekStart(vMaxDate-vCal_FD)+vCal_FD;
Let vRefDate		= AddYears(YearStart(vWeekStart-vCal_RD+7)+vCal_RD-1,1);
Let vEndDate 		= WeekStart(vRefDate-vCal_FD)+vCal_FD-1;

// --- Generate a help table with all weeks of one year ---------------------------------------------------------
WeeksOfOneYear445:
Load
	If(MonthOfQuarter=1 and WeekOfMonth=1,(RecNo()-1)*7,Peek(QuarterOffset)) 
												as QuarterOffset,
	If(WeekOfMonth=1,(RecNo()-1)*7,Peek(MonthOffset)) 
												as MonthOffset,
	Num(RecNo(),'00')							as Week,
	*;
Load 										// --------------------------------------- Generate all Weeks -------
	Num(RecNo(),'00')							as Month,
	IterNo() 									as WeekOfMonth,
	*
	While IterNo() <= NoOfWeeksInMonth or (Quarter=4 and MonthOfQuarter=3 and IterNo()<=6);
Load 										// --------------------------------------- Generate 12 Months -------
	RecNo() 									as Quarter,
	IterNo() 									as MonthOfQuarter,
	SubField('4-4-5','-',IterNo()) 				as NoOfWeeksInMonth
	Autogenerate 4
	While IterNo() <= 3;

// --- Create mapping tables based on the help table ------------------------------------------------------------
Get445Quarter: 
Mapping Load Week, Quarter 				Resident WeeksOfOneYear445;
Get445QuarterOffset: 
Mapping Load Week, QuarterOffset 	Resident WeeksOfOneYear445;
Get445Month: 
Mapping Load Week, Month 				Resident WeeksOfOneYear445;
Get445MonthOffset: 
Mapping Load Week, MonthOffset 	Resident WeeksOfOneYear445;

Drop Table WeeksOfOneYear445;

// --- The Calendar ---------------------------------------------------------------------------------------------
WeekBased445:
LOAD *,
	 If(MonthStart = Previous(MonthStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Month_CY'), 1), Peek('Nth Day by Month_CY')), 1) as [Nth Day by Month_CY],
	 If(QuarterStart = Previous(QuarterStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Qtr_CY'), 1), Peek('Nth Day by Qtr_CY')), 1) as [Nth Day by Qtr_CY],
	 If(YearStart = Previous(YearStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Yr_CY'), 1), Peek('Nth Day by Yr_CY')), 1) as [Nth Day by Yr_CY];
Load 										// --------------------------------------- Grain = Year -------------
	Year										as Year, 
	YearStart									as YearStart, 
											// --------------------------------------- Grain = Quarter ----------
	Dual('FQ' & Quarter,Quarter)				as Quarter,
	QuarterStart								as QuarterStart, 
	Dual(Year & ' FQ' & Quarter,QuarterStart)	as YearQuarter,
											// --------------------------------------- Grain = Month ------------
	Dual('FP' & Month,Month) 					as Month,
	MonthStart									as MonthStart, 
	Dual(Year & ' FP' & Month,MonthStart)		as YearMonth,
	Dual('FP' & MonthOfQuarter,MonthOfQuarter) 	as MonthOfQuarter,
											// --------------------------------------- Grain = Week -------------
	Dual('FW' & Week,Week)						as Week,
	WeekStart									as WeekStart, 
	Dual(Year & ' FW' & Week,WeekStart)			as YearWeek,
	Dual('FW' & WeekOfMonth,WeekOfMonth)		as WeekOfMonth,
											// --------------------------------------- Grain = Day --------------
	DayOfYear									as DayOfYear, 
	DayOfQuarter								as DayOfQuarter, 
	DayOfMonth									as DayOfMonth, 
	WeekDay										as WeekDay,
	Date as [Invoice Date],
	If(ApplyMap('Holiday', Date, Null()) or Match(WeekDay, 'Sat', 'Sun'), 1, 0) as HolidayFlag;
Load  										// ------------------------------------------------------------------
	Mod(Month-1,3)+1 							as MonthOfQuarter,
	Div(Date-MonthStart,7)+1					as WeekOfMonth,
	Date-QuarterStart+1							as DayOfQuarter,
	Date-MonthStart+1							as DayOfMonth,
	*;
Load  										// ------------------------------------------------------------------
	ApplyMap('Get445Quarter',Week,'ERROR') 		as Quarter,
	ApplyMap('Get445Month',Week,'ERROR') 		as Month,
	Date(YearStart+ApplyMap('Get445QuarterOffset',Week,'ERROR'))
											 	as QuarterStart,
	Date(YearStart+ApplyMap('Get445MonthOffset',Week,'ERROR'))
											 	as MonthStart,
	*;
Load  										// ------------------------------------------------------------------
	Num(Div(Date-YearStart,7)+1,'00')			as Week,
	Date-YearStart+1 							as DayOfYear,
	*;
Load  										// ------------------------------------------------------------------
	Year(RefDate) 								as Year,
	Dual(WeekDay(Date),Date-WeekStart)			as WeekDay,
	Date(WeekStart(RefDate-$(vCal_FD))+$(vCal_FD)) 
												as YearStart,
	*;
Load  										// ------------------------------------------------------------------
	Date(YearStart(WeekStart-$(vCal_RD)+7)+$(vCal_RD)-1) 
												as RefDate,
	*;
Load  										// ------------------------------------------------------------------
	Date(WeekStart(Date-$(vCal_FD))+$(vCal_FD))	as WeekStart,
	*;
Load  										// ------------------------------------------------------------------
	Date($(vStartDate)+RecNo()) 				as Date
Autogenerate vEndDate - vStartDate ;
farheenayesha
Creator
Creator
Author

Thank you so much .............for sharing this logic Sunny. Very thankful to you 🙂 

However with this code holidays are getting excluded properly. Please find the snapshot below. 

2nd Jan is a holiday, hence counter should start from 3rd Jan. However it is staring from 2nd Jan itself. 

 

farheenayesha
Creator
Creator
Author

 

Capture3.JPG

 

 

 

 

 

 

Please find the snapshot. 

 

 

 

 

 

 

farheenayesha
Creator
Creator
Author

This code is considering every Friday as holiday but not the holiday list.

sunny_talwar

Changed the def. of the flags a little bit... check this

WeekBased445:
LOAD *,
	 If(MonthStart = Previous(MonthStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Month_CY'), 1), Peek('Nth Day by Month_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Month_CY],
	 If(QuarterStart = Previous(QuarterStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Qtr_CY'), 1), Peek('Nth Day by Qtr_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Qtr_CY],
	 If(YearStart = Previous(YearStart),
	 	If(HolidayFlag = 0, RangeSum(Peek('Nth Day by Yr_CY'), 1), Peek('Nth Day by Yr_CY')), If(HolidayFlag = 0, 1, 0)) as [Nth Day by Yr_CY];
farheenayesha
Creator
Creator
Author

Thanks for the reply Sunny. The new code is working fine for Month but showing the same values as Month for QTR and Year.  I am trying to understand your code. Meanwhile could you please help me to resolve Qtr and Year.