phone: (540)338-0194
email: ken@kenhamady.com

 ReCrystalize

The number of "Work Hours" between two DateTime Values:

Formula #1 calculates the number of working days between two dates (excluding weekends and holidays).  This formula takes it one step further by allowing you to calculate the number of business hours between two DateTime values.  This code is an improved version of the code shown on this page before 2021.  It automatically handles start and end times that fall outside the business day.  It allows you to assign business hours on any day of the week and vary the hours on each day of the week.  And it is all done in this one formula.

In the first two lines you put in your fields for BeginDateTime and EndDateTime.  Below that you put in the start time and end time for each day of the week. Each day of the week can have a different start and end time. Below that you can add a list of holiday dates. These dates are entered for each year, and the list can include holiday dates for multiple years into the future. The code below holiday list should not be changed.

The result of this formula is elapsed hours in decimal format.  If you want to convert this to an elapsed time string format (HH:MM) you can use formula #9.  Formula #9 needs a value in seconds and this formula is in hours, so you should multiply this formula by 3600 when you use it in formula #9. You can do this on the second line of formula #9.
 
Local DateTimeVar BeginDate := {Your.BeginDT}; //Your Begin DateTime
Local DateTimeVar EndDate := {Your.EndDT}; //Your End DateTime

//Specify your start and end times for each day.
//Set both to Time(0,0,0) for non-working days.
TimeVar Range Array BusTimes; 
Redim BusTimes[7];
BusTimes [1] := Time(0,0,0) to Time( 0,0,0); //Sunday
BusTimes [2] := Time(7,0,0) to Time(20,0,0); //Monday
BusTimes [3] := Time(7,0,0) to Time(20,0,0); //Tuesday
BusTimes [4] := Time(7,0,0) to Time(20,0,0); //Wenesday
BusTimes [5] := Time(7,0,0) to Time(20,0,0); //Thursday
BusTimes [6] := Time(7,0,0) to Time(20,0,0); //Friday
BusTimes [7] := Time(0,0,0) to Time( 0,0,0); //Saturday

DateVar Array Holidays := [
Date (2020,01,1), //add additional holidays between these two
Date (2019,12,25)
]; 

//////////////////////// Nothing user configurable below. 

Local NumberVar MinBeginDT :=(
Local TimeVar BusDayBeg := Minimum( BusTimes[DayOfWeek (BeginDate)]);
Local TimeVar BusDayEnd := Maximum( BusTimes[DayOfWeek (BeginDate)]);

Local TimeVar B := Maximum ([Time (BeginDate) , BusDayBeg]);
Local TimeVar E := 
if Date(BeginDate) <> Date(EndDate) then BusDayEnd else
if Time(EndDate) > BusDayEnd then BusDayEnd else 
if Time(EndDate) < BusDayBeg then BusDayBeg else 
Time (EndDate);


if Minimum( BusTimes[DayOfWeek (BeginDate)]) = Time(0,0,0) //A non working day
or Date(BeginDate) in Holidays // A Holiday
or B > BusDayEnd //An event that start after the Business Day Ends
then 0
else (E - B) /(60*60); );

Local NumberVar MinEndDT :=(
Local TimeVar BusDayBeg := Minimum( BusTimes[DayOfWeek (EndDate)]);
Local TimeVar BusDayEnd := Maximum( BusTimes[DayOfWeek (EndDate)]);

Local TimeVar B := BusDayBeg;
Local TimeVar E := 
if Time(EndDate) > BusDayEnd then BusDayEnd else 
Time (EndDate);


if Minimum( BusTimes[DayOfWeek (EndDate)]) = Time(0,0,0) //A non working day
or Date(EndDate) in Holidays // A Holiday
or Date(EndDate) = Date(BeginDate) // Single Day Events are handled above
or E < BusDayBeg //An event that ends before the Business Day Starts
then 0
else (E - B) /(60*60);); 

Local NumberVar MinWhole :=(
Local DateVar Begin := Date (BeginDate);
Local DateVar End := Date (EndDate);
if End < Begin then End := Begin;
Local numberVar i;
Local NumberVar BusMinutes;
Local NumberVar RawDays := End - Begin;
If RawDays > 1 then 
For i := 1 to RawDays-1
do( if DayofWeek (Begin +i) in 2 to 6 and not (Begin +i in Holidays)
then BusMinutes := BusMinutes 
+(Maximum(BusTimes[DayofWeek(Begin+i)]) - Minimum(BusTimes[DayofWeek(Begin+i)]))
);

BusMinutes/60/60 );

(MinEndDT + MinBeginDT + MinWhole)