Forum Discussion
Calculate Date and Time difference considering the weekends and workhours
- 10 years ago
The only possibility I can think of is that there is something wrong with the Calendar'[WorkDay] formula. Could you please check this column formula is like below? The data type of this column should be “True/False”.
If it is actually same as mine, could you please upload your .pbix file to OneDrive and share it with me? In that case I can take a look at your .pbix file and try to solve the problem.
Best Regards,
Herbert
- 9 years ago
How about the result if we update the “FirstDaySecDiff” measure as below?
FirstDaySecDiff = IF ( Table1[FirstDayEndTime] >= Table1[DateTimeFrom] && Table1[FirstDayEndTime] <= Table1[DateTimeTo], DATEDIFF ( Table1[DateTimeFrom], Table1[FirstDayEndTime], SECOND ), IF ( Table1[FirstDayEndTime] >= Table1[DateTimeFrom] && Table1[FirstDayEndTime] > Table1[DateTimeTo], DATEDIFF ( Table1[DateTimeFrom], Table1[DateTimeTo], SECOND ), 0 ) )Best Regards,
Herbert
Really appreciate the work y'all put in to get a working DAX solution. I turned it into a custom M function so that you can easily apply it to multiple columns without having a ton of duplication. Also fixed a couple of small bugs that were in the original DAX.
To use, just copy this into a new blank query and should work out of the box.
Of course you're free to change the start/end times (currently at 8am and 5pm) etc
(from, to) => let
// utility functions
dateWithSetTime = (dt, t) => DateTime.From(Date.ToText(Date.From(dt)) & " " & Time.ToText(t)),
max2 = (first, second) => if first > second then first else second,
min2 = (first, second) => if first < second then first else second,
isBetween = (t, first, last) => t >= first and t <= last,
isWeekend = (day) => Date.DayOfWeek(day) = 5 or Date.DayOfWeek(day) = 6,
isWorkday = (day) => not isWeekend(day),
numDaysBetween = (f, t) =>
let
start = Date.AddDays(Date.From(from), 1),
length = Duration.Days(Date.From(to) - Date.From(from)) - 1,
dates = List.Dates(start, length, #duration(1, 0, 0, 0)),
workdays = List.Select(dates, each isWorkday(_))
in
List.Count(workdays),
dur = (days) => Duration.From(days),
// variables and initial setup
startTime = #time(8,0,0),
endTime = #time(17,0,0),
firstDayStartTime = dateWithSetTime(from, startTime),
firstDayEndTime = dateWithSetTime(from, endTime),
lastDayStartTime = dateWithSetTime(to, startTime),
lastDayEndTime = dateWithSetTime(to, endTime),
endsOnStartDay = Date.From(from) = Date.From(to),
// get seconds for first, middle, and last days
firstDaySeconds =
// make sure that end date is after start date
if from > to then error "The start date is greater than the end date. Make sure that you passed the arguments in the right order." else
// record 0 time if weekend, starts after day ends, or ends before day starts
if isWeekend(Date.From(from)) or from > firstDayEndTime or to < firstDayStartTime
then dur(0)
else min2( to, firstDayEndTime ) - max2( from, firstDayStartTime ),
middleDaysSeconds =
if endsOnStartDay
then dur(0)
else (endTime - startTime) * numDaysBetween(from, to),
lastDaysSeconds =
// record 0 time if holiday, weekend, already counted, or ends before day starts
if isWeekend(Date.From(to)) or endsOnStartDay or to < lastDayStartTime
then dur(0)
else min2(to, lastDayEndTime) - lastDayStartTime,
totalSeconds = Duration.TotalSeconds(firstDaySeconds + middleDaysSeconds + lastDaysSeconds)
in
totalSeconds / 3600- itshudak7 years ago
Helper I
Sam,
I am actually running into an issue on some of the output.
FirstStartDateTime: 10/7/2017 1:20:00 PM
CreateDate: 10/10/2017 8:39:18 AM
An error occurred in the ‘’ query. Expression.Error: The 'increment' argument is out of range.
Details:
1.00:00:00I'm not sure what is happening here. I kept everything the same, and also changed the startTime, but am getting the same error. Any ideas?
- Anonymous7 years agoNot applicable
itshudak looks like you passed the arguments in the wrong order (doing that reproduced the exact error for me).
I've updated my code above to give a helpful error message in that case
- itshudak7 years ago
Helper I
Reversing the inputs actually gives me the same error, but 10 times worse. The output should be positive, correct? Regardless, I don't know what this error is actually saying, but my data looks correct, so I don't think it's a formatting issue. I'm just confused as to what needs to be fixed to get it to work properly. I have 100k rows that work, but these 100 or so errors have got me for a loop.
- Anonymous7 years agoNot applicable
Anonymous this is fantastic, thank you so much! I did have to make one small change to get the hours to calculate properly - using the default Date.DayofWeek settings, the weekends are days 0 and 6 rather than 5 and 6.