Calculate Working Time between Two Dates in C# (including SLA Working Hours)

Often we need to calculate the time between two dates, but only take into account working hours. Working hours usually fall somewhere between 09:00 - 17:00, Monday - Friday, and are defined in CRM via Entitlements and SLAs. There's no way to achieve this out of the box, therefore custom code must be written for this calculation within a plugin or a workflow.

The code I provide in this article is one of many ways this can be achieved. My approach here is to abstract days, minutes and time duration programatically and to then provide a static Calendar class to deal with CRM-specific logic.

Minute's are straightforward. You'll see here I simply conceptualise them as an object that has an Index property to represent which minute of the day the minute is. For example a minute with Index is 00:10.

One level higher, I outline a day, which has a list of minutes (there are 1440 minutes in a day):

Then we have a duration, which is a collection of days between a start and an end:

Finally we have a static calendar class which handles CRM-specific entitlement and SLA logic. This currently only works for retrieving an Entitlement from a Case. Attribute strings can be changed according to your requirement/the entity you're working with.

How is this used?

Firstly, the 4 classes from above are copied into a project.

Next, in the plugin's execute method, two DateTimes are retrieved, along with the context entity. In this example I'm using a Case entity and my Calendar class:

We now have a list of days representing a model of working hours defined in the Case's Entitlement stored in the workingHours variable.

We can now create a duration object, which models the time between our two DateTimes:

Then we remove time which we're not interested in (it falls outside of valid working hours):

And finally call GetTotalMinutes() and calculate the time in minutes between our two DateTimes without the invalid time:

And that's all. We now have the valid working time (in minutes) between the two DateTimes stored in the responseTime variable.

7 comments:

  1. Hi,
    Thank you for posting this and it is very helpful.
    I have used the same code in order to identify the time difference b/w two fields in Lead entity and it is working as expected. But I have a small issue, If both dates are same, it is giving me 0. Also if I have a 6 days and 2 hours differnce it is excluding the hours/minutes from the last day.
    Could you please help me to resolve ?

    Many Thanks,
    Abhiram

    ReplyDelete
  2. This is great thanks. Could it be amended to take into account the Holiday schedule configured within the business hours calander?

    ReplyDelete
  3. Hello,

    Please i can't foud Helpers class ?

    thanks

    ReplyDelete
  4. Thanks a lot for this. The working hours were being taken only from the first calendar rule and wasn't considering the other calendar rules.

    ReplyDelete
    Replies
    1. Exactly, I'm trying to understand how to manage the rules of the calendar to consider, for example, the break time. I also don't know why it don't calculate the minutes on the same day.
      When i fix them i will put the code here.

      Delete
    2. It seems that apply the first rule it find in the calendarrules to all the days of the working week, therefore if you have an half working day (ex: Friday) it will be calculated as a standard working day.

      Delete
  5. OK, i found the solution.
    All the code written above can be summarized in:
    ExpandCalendarRequest calendarrequest = new ExpandCalendarRequest();
    calendarrequest.CalendarId = calendar.Id;
    calendarrequest.Start = utcStart;
    calendarrequest.End = utcEnd;
    ExpandCalendarResponse expandedCalendarResponse = service.Execute(calendarrequest) as ExpandCalendarResponse;

    ReplyDelete