Business Hours Calculations with Apex

Business HoursSalesforce provides a simple mechanism for setting business hours in your organization.  Just navigate to:

Setup -> Administration Setup -> Company Profile -> Business Hours

Which brings you to this screen:

Business Hours Configuration

You set the hours for each day of the week that the company is available.  I’m using a single Business Hours record named Default.  You can have multiple business hours in multiple time zones if you have a complex support organization.  With business hours you can work in specific time zones and locations with:

  • Cases
  • Case escalation rules
  • Case milestones in entitlement processes

This is accessible through Apex, but you will likely need to customize the logic to your needs.  Salesforce thoughtfully provides a BusinessHours class, but it is very basic, just 3 methods.  Since I needed to check if today was a business day and a few other things I had to write it myself.

Here is the Apex code:

 1 public class BusinessDays {
 2
 3 private List<Boolean> businessDay = new Boolean[7];
 4 private List<Time> startHours = new Time [7];
 5 private List<Time> endHours = new Time [7];
 6 private Date knownSunday = date.newInstance(2013, 1, 6);
 7 
 8   // Constructor creates businessDay array
 9   public BusinessDays() {
10
11     BusinessHours bh =
12       [Select
13         SundayStartTime, MondayStartTime, TuesdayStartTime,
14         WednesdayStartTime, ThursdayStartTime, FridayStartTime,
15         SaturdayStartTime, SundayEndTime, MondayEndTime,TuesdayEndTime,
16         WednesdayEndTime, ThursdayEndTime, FridayEndTime,SaturdayEndTime
17       From BusinessHours 
18       Where IsDefault=true];
19
20     businessDay[0] = (bh.SundayStartTime != null);
21     businessDay[1] = (bh.MondayStartTime != null);
22     businessDay[2] = (bh.TuesdayStartTime != null);
23     businessDay[3] = (bh.WednesdayStartTime != null);
24     businessDay[4] = (bh.ThursdayStartTime != null);
25     businessDay[5] = (bh.FridayStartTime != null);
26     businessDay[6] = (bh.SaturdayStartTime != null);
28  
29     startHours[0] = bh.SundayStartTime;
30     startHours[1] = bh.MondayStartTime;
31     startHours[2] = bh.TuesdayStartTime;
32     startHours[3] = bh.WednesdayStartTime;
33     startHours[4] = bh.ThursdayStartTime;
34     startHours[5] = bh.FridayStartTime;
35     startHours[6] = bh.SaturdayStartTime;
36
37     endHours[0] = bh.SundayEndTime;
38     endHours[1] = bh.MondayEndTime;
39     endHours[2] = bh.TuesdayEndTime;
40     endHours[3] = bh.WednesdayEndTime;
41     endHours[4] = bh.ThursdayEndTime;
42     endHours[5] = bh.FridayEndTime;
43     endHours[6] = bh.SaturdayEndTime;
44
45   }
46
47   // Check if today is a business day
48   public Boolean isBusinessDay(Date inputDate) {
49     // index i is index into the businessDay array based on inputDate
50     Integer i = Math.mod(Math.abs(this.knownSunday.daysBetween(inputDate)),7);
51     return (businessDay[i]);
52    }
53  
54   // Get the start time
53   public Time getStartTime(Date inputDate) {
54     Integer i = Math.mod(Math.abs(this.knownSunday.daysBetween(inputDate.date)),7);
55     return (startHours[i]);
56   }
57
58   // Gets next business day, skipping non business days
59   public Date nextBusinessDay(Datetime inputDatetime) {
60     Integer i = 
61       Math.mod(Math.abs(this.knownSunday.daysBetween(inputDatetime.date())),7);
62     Datetime returnDate = inputDatetime;
63     while (!businessDay[Math.mod(i, 7)]) {
64       i++;
65       returnDate = returnDate.addDays(1);
66     }
67     return returnDate.date;
68   }
69
70 }

I build 3 arrays.  One to hold the days of the week the company is open, one to hold the start time for each day, and one to hold the end time of each day.  I’m not using the end time array at the moment, it is available just in case.

Notice the variable knowSunday on line 6.  You could also use the method Date.toStartOfWeek(), but you would have to match the indexes to the locale of your company.  According to the Apex reference:  “…the start of a week is Sunday in the United States locale, and Monday in European locales.”  I usually work for US companies, but I’ve gotten in trouble before by making assumptions about locale dependent information when working for customers in Europe.

If you want to know if we are open for business today:

  if (busDays.isBusinessDay(Date.today())) { ...
If you want to know when we open the doors for customers:
  if (busDays.getStartTime(Date.today())) { ...

If you want to know what the next day we are open:

  Datetime nextBusDay = busDays.nextBusinessDay(Datetime.now());

These are just a few of the possibilities.  The customers I’ve worked for always seem to have their own unique rules for determining when to send the invoice, how to calculate the date in that custom field, and so on.  The bad news is that almost nothing is pre-built in the API.  The good news is that we can use Apex to implement whatever rules our customers dream up.

View Our Other Helpful Salesforce Guides