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

Be one of the first to start using Fabric Databases. View on-demand sessions with database experts and the Microsoft product team to learn just how easy it is to get started. Watch now

Reply
eaglesilo
Regular Visitor

DAX Help: Measure of Working Minutes between two times

Howdy there.  I'm stuck.

 

I'm trying to build a DAX measure that will calculate the working minutes between two datetime objects but just can't figure it out. Has anyone solved this before? I feel like it should be easy, I just can't wrap my head around the solution.

Below is my attempt, but it's returning working minutes for the entire day, not just between the start and end time for each day:

 

eaglesilo_6-1709848019616.png

 

 

For the above records, here's what I expect the value to show:

IdCreatedTimepostedTimeworkingMinutes 0700-1630
1136702024-02-27 11:55:00.000 -06:002024-02-28 10:06:36.000 -06:00461
1137202024-02-28 06:59:00.000 -06:002024-02-28 09:09:32.000 -06:00129
1136722024-02-27 11:56:00.000 -06:002024-02-27 12:08:16.000 -06:0012
1136622024-02-27 10:57:00.000 -06:002024-02-27 11:14:24.000 -06:0017
1136012024-02-26 15:31:00.000 -06:002024-02-27 07:49:56.000 -06:00108
1133612024-02-22 11:53:00.000 -06:002024-02-26 07:31:38.000 -06:00878
1133592024-02-22 11:44:00.000 -06:002024-02-22 14:53:08.000 -06:00189
1133402024-02-22 09:58:00.000 -06:002024-02-22 14:33:42.000 -06:00275
1133922024-02-22 13:19:00.000 -06:002024-02-22 13:21:34.000 -06:002
1131952024-02-20 13:02:00.000 -06:002024-02-20 13:14:18.000 -06:0012
1131422024-02-20 09:02:00.000 -06:002024-02-20 10:12:01.000 -06:0070
 

 

Working Hours are typically defined as 0700-1630 CST.

Here's the DAX I was trying so far, but I know it's, to an extent, not even directionally accurate for how I'm supposed to do it. (In the above screenshot, I expect the Total line to be the SumTotal of each individual Load Id value.)

_m_CreatedPosted_Time_cgpt = 
var createdTime = min(####Data[createdTime]) 
var PostedTime = min(###LoadPostingID[PostedTime])
RETURN
-- Calculate the total working minutes between StartDateTime and EndDateTime
SUMX (
    -- Generate a row for each date between StartDateTime and EndDateTime
        CALCULATETABLE (
        Calendar_DateRangePicker,
        DATESBETWEEN (
            Calendar_DateRangePicker[DateId],
            createdTime,
            PostedTime
        ),
        Calendar_DateRangePicker[IsBusinessDay####] = TRUE ()
    ),
    -- For each date, calculate the working minutes based on business hours
    IF (
        Calendar_DateRangePicker[DateId] = createdTime && HOUR(createdTime) < hour(Calendar_DateRangePicker[StartTime]), // If createdTime is before 07:00
        IF (
            HOUR(postedTime) >= hour(Calendar_DateRangePicker[EndTime]), // If postedTime is after or at 16:30
            DATEDIFF(Calendar_DateRangePicker[StartTime], Calendar_DateRangePicker[EndTime], MINUTE),
            DATEDIFF(Calendar_DateRangePicker[StartTime], postedTime, MINUTE)
        ),
        IF (
            Calendar_DateRangePicker[DateId] = postedTime && HOUR(postedTime) >= hour(Calendar_DateRangePicker[EndTime]), // If postedTime is after or at 16:30
            DATEDIFF(Calendar_DateRangePicker[StartTime], Calendar_DateRangePicker[EndTime], MINUTE),
            DATEDIFF(Calendar_DateRangePicker[StartTime], Calendar_DateRangePicker[EndTime], MINUTE)
        )
    )
)

I do have a Calendar table which includes the Start and End working time for each day, and indicates if a day is a Business Day. (The business hours are generally 0700-1630.)

Here's the relevant tables from the data model:

 
eaglesilo_5-1709847986822.png

 

 

 

I feel the answer in here is something with a Calculated Table, but I can't figure out how that is supposed to work.

*After I get the answer I want here, I'll then get the Count of values so I can run the Average. I do want to have a measure that's just Totals, though, so I could use that for other things if needed, for why I'm not trying to get the Average directly in this DAX.

 

Appreciate any help you can provide!

1 ACCEPTED SOLUTION
lbendlin
Super User
Super User

You say working minutes but your second timestamp is on seconds granularity.  Please clarify. As you can see we have some slight disagreements on the duration.

 

lbendlin_0-1709948099991.png

You need to decide if you want to include or exclude the minute of the postedTime  timestamp.

lbendlin_1-1709948406791.png

 

What should happen when the time interval spreads over weekends and holidays? For now I assume you observe weekends on saturday and sunday, and have no holidays.

 

wm =
VAR a =
    GENERATESERIES (
        ROUNDDOWN ( [CreatedTime] * 1440, 0 ),
        ROUNDDOWN ( [postedTime] * 1440, 0 )
    )
VAR b =
    ADDCOLUMNS (
        FILTER ( CALENDAR ( [CreatedTime], [postedTime] ), WEEKDAY ( [Date], 2 ) < 6 ),
        "v", ROUNDDOWN ( [Date], 0 ) * 1440
    )
VAR c =
    GENERATE ( b, GENERATESERIES ( [v] + 420, [v] + 990 ) )
RETURN
    COUNTROWS ( INTERSECT ( a, SELECTCOLUMNS ( c, "Value", [Value] ) ) )

 

 

View solution in original post

3 REPLIES 3
lbendlin
Super User
Super User

You say working minutes but your second timestamp is on seconds granularity.  Please clarify. As you can see we have some slight disagreements on the duration.

 

lbendlin_0-1709948099991.png

You need to decide if you want to include or exclude the minute of the postedTime  timestamp.

lbendlin_1-1709948406791.png

 

What should happen when the time interval spreads over weekends and holidays? For now I assume you observe weekends on saturday and sunday, and have no holidays.

 

wm =
VAR a =
    GENERATESERIES (
        ROUNDDOWN ( [CreatedTime] * 1440, 0 ),
        ROUNDDOWN ( [postedTime] * 1440, 0 )
    )
VAR b =
    ADDCOLUMNS (
        FILTER ( CALENDAR ( [CreatedTime], [postedTime] ), WEEKDAY ( [Date], 2 ) < 6 ),
        "v", ROUNDDOWN ( [Date], 0 ) * 1440
    )
VAR c =
    GENERATE ( b, GENERATESERIES ( [v] + 420, [v] + 990 ) )
RETURN
    COUNTROWS ( INTERSECT ( a, SELECTCOLUMNS ( c, "Value", [Value] ) ) )

 

 

Thank you for the reply.  As you can see in my table, I have a Calendar_DateRangePicker[IsBusinessDay] field which takes care of Working vs Non Working days. 

 

In the various screenshots, I did not truncate the times to the nearest minute, but if we need to do that before we can proceed with getting to working minutes, we can.  You can choose to round in whichever direciton you wish for now.

As you can see in my table, I have a Calendar_DateRangePicker[IsBusinessDay] field which takes care of Working vs Non Working days.

You can modify my code accordingly to replace the WEEKDAY  filter with your IsBusinessDay filter.

Helpful resources

Announcements
Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount!

ArunFabCon

Microsoft Fabric Community Conference 2025

Arun Ulag shares exciting details about the Microsoft Fabric Conference 2025, which will be held in Las Vegas, NV.

December 2024

A Year in Review - December 2024

Find out what content was popular in the Fabric community during 2024.