Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Join us for an expert-led overview of the tools and concepts you'll need to become a Certified Power BI Data Analyst and pass exam PL-300. Register now.

Reply
Keston
Frequent Visitor

Working Hours Between two date/time fields

Hello,

 

Seeking the assistance of the forum, I have two date/time fields in the following format and the following script to calculate the working hours between 8 - 1700 excluding weekend. The script is calculating same day correctly however, if the dates spans between multiple days the hours are incorrect as see below.

Can someone help me modify this script or provide a solution for me? I'm really struggling here to get the working hours.

Same day calculation

Keston_0-1725816419793.png

Mutiple days

Keston_1-1725816571443.png

 

Script

WorkingHoursDuration =
VAR StartDateTime = [date/time]
VAR EndDateTime = [date/time]

-- Define working hours
VAR StartOfWorkday = TIME(8, 0, 0)
VAR EndOfWorkday = TIME(17, 0, 0)

-- Helper function to calculate working hours in a given interval
VAR CalculateWorkingHoursInInterval =
VAR IntervalStart = MAX(DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + StartOfWorkday, StartDateTime)
VAR IntervalEnd = MIN(DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + EndOfWorkday, EndDateTime)
RETURN
IF (
IntervalEnd > IntervalStart,
DATEDIFF(IntervalStart, IntervalEnd, MINUTE) / 60.0,
0
)

-- Adjust start and end times if they fall outside working hours
VAR AdjustedStartTime =
IF (
WEEKDAY(StartDateTime, 2) > 5 || StartDateTime < DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + StartOfWorkday,
DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + StartOfWorkday,
IF (
StartDateTime > DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + EndOfWorkday,
DATE(YEAR(StartDateTime), MONTH(StartDateTime), DAY(StartDateTime)) + EndOfWorkday,
StartDateTime
)
)

VAR AdjustedEndTime =
IF (
WEEKDAY(EndDateTime, 2) > 5 || EndDateTime > DATE(YEAR(EndDateTime), MONTH(EndDateTime), DAY(EndDateTime)) + EndOfWorkday,
DATE(YEAR(EndDateTime), MONTH(EndDateTime), DAY(EndDateTime)) + EndOfWorkday,
IF (
EndDateTime < DATE(YEAR(EndDateTime), MONTH(EndDateTime), DAY(EndDateTime)) + StartOfWorkday,
DATE(YEAR(EndDateTime), MONTH(EndDateTime), DAY(EndDateTime)) + StartOfWorkday,
EndDateTime
)
)

-- Calculate working hours if the interval is within the same day
VAR SameDayHours =
IF (
DATEVALUE(AdjustedStartTime) = DATEVALUE(AdjustedEndTime),

0
)

-- Calculate working hours for full working days between start and end dates
VAR FullDaysStart = DATE(YEAR(AdjustedStartTime), MONTH(AdjustedStartTime), DAY(AdjustedStartTime)) + 1
VAR FullDaysEnd = DATE(YEAR(AdjustedEndTime), MONTH(AdjustedEndTime), DAY(AdjustedEndTime)) - 1

VAR FullDaysHours =
IF (
FullDaysStart <= FullDaysEnd,
CALCULATE (
SUMX (
FILTER (
CALENDAR (FullDaysStart, FullDaysEnd),
WEEKDAY([Date], 2) <= 5
),
9
)
),
0
)

-- Calculate working hours for the start and end days
VAR StartDayHours =
IF (
DATEVALUE(AdjustedStartTime) < DATE(YEAR(AdjustedStartTime), MONTH(AdjustedStartTime), DAY(AdjustedStartTime)) + EndOfWorkday,
VAR IntervalStart = MAX(StartOfWorkday, AdjustedStartTime)
VAR IntervalEnd = DATE(YEAR(AdjustedStartTime), MONTH(AdjustedStartTime), DAY(AdjustedStartTime)) + EndOfWorkday
RETURN
CalculateWorkingHoursInInterval,
0
)

VAR EndDayHours =
IF (
DATEVALUE(AdjustedEndTime) > DATE(YEAR(AdjustedEndTime), MONTH(AdjustedEndTime), DAY(AdjustedEndTime)) + StartOfWorkday,
VAR IntervalStart = DATE(YEAR(AdjustedEndTime), MONTH(AdjustedEndTime), DAY(AdjustedEndTime)) + StartOfWorkday
VAR IntervalEnd = MIN(EndOfWorkday, AdjustedEndTime)
RETURN
CalculateWorkingHoursInInterval,
0
)

-- Total working hours
VAR TotalWorkingHours =
SameDayHours + FullDaysHours + StartDayHours + EndDayHours

RETURN
MAX(0, TotalWorkingHours)

15 REPLIES 15
Keston
Frequent Visitor

I have the details, so working hours is 8 - 1700 GMT-4 Monday to Fridday.

Good.  What is your required granularity level - half hour slots ok, or does it need to go down to minute level?

 

Please provide a couple of sample intervals in usable format, not as a screenshot.

Down to the minute will be ideal.

lbendlin_0-1725831535018.png

This is immutable data so I created a calculated column.

 

Work hours = 
var workingdays = FILTER(CALENDAR([Created],[Assigned]),WEEKDAY([Date],2)<6)
var possibleworkingminutes = SELECTCOLUMNS(GENERATE(workingdays,GENERATESERIES([Date]*1440+480,[Date]*1440+1019)),"Value",[Value])
var fullinterval = GENERATESERIES(ROUNDDOWN([Created]*1440,0),ROUNDDOWN([Assigned]*1440,0)-1)
var actualworkingminutes = INTERSECT(possibleworkingminutes,fullinterval)
RETURN ROUNDDOWN(countrows(actualworkingminutes)/60,0) & Format(countrows(actualworkingminutes)/1440,":nn")

 

 

Thank you for this but for some strange reason I'm receiving the folowing error.

The start date in Calendar function can not be later than the end date.

You and I have different date formats. You use dd/mm/yyyy and I use mm/dd/yyyy.  Neither are good formats. Best to use ISO-8601 to avoid ambiguity.

Hey lbendlin

I'm still receiving this error: The start date in Calendar function can not be later than the end date. Is it possible to update the script to probably exclude these instances?

Thanks.

Please provide sample data that covers your issue or question completely, in a usable format (not as a screenshot).

Do not include sensitive information or anything not related to the issue or question.

If you are unsure how to upload data please refer to https://community.fabric.microsoft.com/t5/Community-Blog/How-to-provide-sample-data-in-the-Power-BI-...

Please show the expected outcome based on the sample data you provided.


Hi lbendlin,

 

I found an issue with my data, it appears that the assigned time field may be blank at times. I also simulated with the Work hours.pbix. How can we take this into consideration?

Thank you for your support.

You can choose to ignore these rows, or replace the blanks with an appropriate date. Not sure if "Today"  is appropriate for this?

Hey lbendlin,

 

So I added Now() to the blank field and this worked well.

However, now I observed the root of the issue, I have a few instances were the created date is later than the assigned date, I'm not sure why this would have occured.

But, do you have any recommendations to the script to exlucde these instances?

You could use ABS() to always get a positive duration.

Ok noted, just to be clear, I should replace CALENDAR() with ABS()?

var workingdays = FILTER(CALENDAR(MIN([Created],[Assigned]),MAX([Created],[Assigned])),WEEKDAY([Date],2)<6)
lbendlin
Super User
Super User

There's no need for any of this, you can use a simple INTERSECT. 

 

BUT - only if you clearly define what "working hours"  means  - which days, which time zones etc.  Do you have that information?

Helpful resources

Announcements
Join our Fabric User Panel

Join our Fabric User Panel

This is your chance to engage directly with the engineering team behind Fabric and Power BI. Share your experiences and shape the future.

June 2025 Power BI Update Carousel

Power BI Monthly Update - June 2025

Check out the June 2025 Power BI update to learn about new features.

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.