This knowledge article walks you through calculating the duration between two timestamps based on Business Hours in Salesforce. It explains how to use an Apex class with the BusinessHours.diff() method, integrate it with a Flow, and store the calculated duration in hours on a record for reporting and automation purposes.
To calculate the time taken between two events, such as Created Date and Completed Date, only during Business Hours, for use cases such as:
● Task completion time
● SLA tracking
● Case resolution time
Follow the steps below to configure Business Hours in Salesforce.
Step 1: Configure Business Hours
Step 2: Create an Apex Class
Note: The Apex class uses the default Business Hours. Modify the query if using a different Business Hours record
public with sharing class BusinessHoursDurationService {
@InvocableMethod(label='Calculate Business Hours Duration')
public static List<Long> calculate(List<Request> requests) {
Id bhId = [SELECT Id FROM BusinessHours WHERE IsDefault = true LIMIT 1].Id;
List<Long> results = new List<Long>();
for (Request r : requests) {
if (r.startDate == null || r.endDate == null) {
results.add(null);
} else {
results.add(BusinessHours.diff(bhId, r.startDate, r.endDate));
}
}
return results;
}
public class Request {
@InvocableVariable(required=true)
public Datetime startDate;
@InvocableVariable(required=true)
public Datetime endDate;
}
}
Step 3: Create a Test Class
@isTest
public class BusinessHoursDurationServiceTest {
@isTest
static void testCalculate_WithValidDates() {
BusinessHours bh = [SELECT Id FROM BusinessHours WHERE IsDefault = true LIMIT 1];
BusinessHoursDurationService.Request req = new BusinessHoursDurationService.Request();
req.startDate = Datetime.newInstance(2026, 4, 22, 10, 0, 0);
req.endDate = Datetime.newInstance(2026, 4, 22, 12, 0, 0);
List<BusinessHoursDurationService.Request> requests =
new List<BusinessHoursDurationService.Request>{ req };
Test.startTest();
List<Long> results = BusinessHoursDurationService.calculate(requests);
Test.stopTest();
System.assertEquals(1, results.size());
}
}
Step 4: Create a Custom field
Step 5: Create a Record-Triggered Flow
| Trigger the Flow When | A record is updated |
|
Condition Requirements | All Conditions Are Met(AND) |
| Condition |
Status Is Changed = True Status Equals Completed |
| Optimize the Flow for | Actions and Related Records |
| Outcome Label | Condition Requirements | Resource | Operator | Value |
| Start and End Date is not null | All Conditions Are Met (AND) |
{!$Record.CreatedDate} {!$Record.CompletedDateTime} |
Is Null Is Null |
|
Step 6: Add an Apex action to the First Outcome
| Start Date | {!$Record.CreatedDate} |
| End Date | {!$Record.CompletedDateTime} |
{!Calculate_Business_Hours_Duration} / 3600000
Step 7: Add the Assignment Elements
Branch A: For the Start and End Date is not null Outcome
| Variable | Operator | Value |
| {!v_CompletionTimeHours} | Equals | {!Convert_Milliseconds_to_Hours} |
Branch B: For the Default Outcome
| Variable | Operator | Value |
| {!v_CompletionTimeHours} | Equals |
Keep it blank |
Step 8: Add the Update Records Element
| How to Find Records to Update and Set Their Value | Use the task record that triggered the flow |
| Field | Value |
|
Completion_Time_Hours__c or the specific custom field name | {!v_CompletionTimeHours} |
Step 9: Create a Report
Final Outcome:
Considerations:
Best Practices:
_____________________________________________
Written by: Piyusha Pilania | Forum Ambassador
Piyusha is a Salesforce MVP and Golden Hoodie Recipient. She is a seasoned Salesforce consultant with 13 years of experience. She has a wealth of experience and knowledge in Martech, data, and Salesforce, and she has a deep interest in the convergence of data, AI, and Salesforce. She also leads the Slack and Salesforce community groups. Her mission is to elevate the knowledge and skills of trailblazers and to grow the Salesforce community.
Submissions reflect only the opinions of the user who made available the Submission and not the opinions of Salesforce, regardless of whether the user is affiliated with Salesforce, and may contain or constitute products, services, information, data, content and other materials made available by or on behalf of third parties ("Third Party Materials). Salesforce neither controls nor endorses, nor is Salesforce responsible for, any Third Party Materials, including their accuracy, validity, timeliness, completeness, reliability, integrity, quality, legality, usefulness or safety, or any applicable intellectual property rights. Any Submissions made available through any message board or forum in response to posted questions, or that otherwise purports to answer any questions, including any questions about Salesforce or Programs, are made available for your general knowledge only and should never be relied upon as answers to your specific questions (even if an answer is marked as a “best” answer or with any similar qualifications). You should always contact Salesforce support for answers to your specific questions. Salesforce has no control over Submissions, and is not responsible for any use or misuse (including any distribution) by any third party of Submissions.
If you have questions, tap into the wisdom of our entire Trailblazer Community here: https://trailhead.salesforce.com/trailblazer-community/feed
005321712

We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.