Forum Discussion
Calculating Network Hours / Working Hours
- Anonymous7 years ago
Anonymous -
Here's the date table that is referenced in the Calculated Column. Notice, it has a Weekend attribute to indicate whether it's a weekend. You could add OffDay, which considers both weekends and holidays.
Date = ADDCOLUMNS(CALENDAR(DATE(2018,1,1),DATE(2020,12,31)),"Weekend",IF(WEEKDAY([Date]) IN {1,7}, TRUE(),FALSE()))Here's a Calculated Column. It works with weekends. The same logic could be used with Is OffDay instead of Weekend. You'd replace the following bits:
var start_date_is_weekend = LOOKUPVALUE('Date'[Weekend],'Date'[Date],INT([Date/Time Opened]))
var end_date_is_weekend = LOOKUPVALUE('Date'[Weekend],'Date'[Date],INT([Date/Time Closed]))
'Date'[Weekend] = FALSE()
Hours Difference = //Define hours of workday, in seconds var work_day_begins = 3600 * 9 //9AM var work_day_ends = 3600 * 17 //5PM var seconds_in_workday = work_day_ends - work_day_begins //Check whether start/end dates occurred on a weekend. var start_date_is_weekend = LOOKUPVALUE('Date'[Weekend],'Date'[Date],INT([Date/Time Opened])) var end_date_is_weekend = LOOKUPVALUE('Date'[Weekend],'Date'[Date],INT([Date/Time Closed])) //Get the seconds from midnight. //If it's a weekend, always use the end of the workday value. //If outside working hours, snap to the start or end of day. var start_time = TIMEVALUE(FORMAT([Date/Time Opened],"HH:mm:ss"))*86400 var end_time = TIMEVALUE(FORMAT([Date/Time Closed],"HH:mm:ss"))*86400 var start_time_adj = IF(start_date_is_weekend,work_day_ends,MIN(MAX(start_time,work_day_begins),work_day_ends)) var end_time_adj = SWITCH( TRUE(), ISBLANK(end_date_is_weekend),BLANK(), end_date_is_weekend,work_day_ends, MIN(MAX(end_time,work_day_begins),work_day_ends) ) //Find the number of workdays var day_diff = COUNTROWS( FILTER( 'Date', [Date] > INT([Date/Time Opened]) && [Date] <= INT([Date/Time Closed]) && 'Date'[Weekend] = FALSE() ) ) //Final calculation: var time_diff = end_time_adj - start_time_adj var working_seconds = (day_diff * seconds_in_workday) + time_diff var working_hours = working_seconds / 3600.00 return IF(ISBLANK([Date/Time Closed]),BLANK(),working_hours)
Anonymous
The solution is quite slow ~6-7 minute load times. I'm working with a data set that is 27K rows that grows each day. Having totals is a pretty big deal for my use case. We are hoping to measure individual and team performance.
Anonymous - Some performance considerations:
Have 2 date tables, each with a relationship with your table. This would require adding columns with Date datatype insead of Date/Time. The Date table could also have a column "relative work days" which could be used to derive the difference between them, instead of counting rows.
You could also have a Time table for each of Start and End. It could have a column which maps all times before working hours to the beginning of the work day and all times after working hours to the end of the work day, and also contain the second of the day. Again, each table would be related to your fact table. Performance could be improved by rounding to the nearest minute and only having 1440 rows in your Time table instead of 86400.
All 4 of these tables should be built in your data source. The good news is they can be built out and can be static.
This link describes performance considerations.
Cheers!
Nathan
- Anonymous7 years agoNot applicable
In fact, ALL of the processing could potentially be done in the source, since it is a row-by-row calculation.
- Anonymous7 years agoNot applicable
Anonymous
I just want to make sure I'm understanding you correctly. Performing the above would create the tables needed to mimic the below logic:
//Find the number of workdays var day_diff = COUNTROWS( FILTER( 'Date', [Date] > INT([Date/Time Opened]) && [Date] <= INT([Date/Time Closed]) && 'Date'[Weekend] = FALSE() ) )Anonymous - Some performance considerations:
Have 2 date tables, each with a relationship with your table. This would require adding columns with Date datatype insead of Date/Time. The Date table could also have a column "relative work days" which could be used to derive the difference between them, instead of counting rows.
You could also have a Time table for each of Start and End. It could have a column which maps all times before working hours to the beginning of the work day and all times after working hours to the end of the work day, and also contain the second of the day. Again, each table would be related to your fact table. Performance could be improved by rounding to the nearest minute and only having 1440 rows in your Time table instead of 86400.
- Anonymous7 years agoNot applicable
Anonymous - That's sort of correct - Instead of counting rows, you would use RELATED to retrieve each "relative work day" number, and then subtract one from the other.