[SalesForce] Calculating business days using BusinessHours class

Our business has a requirement to calculate a due date on a case by using the created date and adding business hours, or business days. When we calculate business days it converts the days to 24 hours and divides the result by the business hours(10 hours) which is giving us wrong due dates.

Example:

If our created date is today(8/5/16) and we add 5 business days it converts it to 120 hours. It then divides the hours by the business hours which is 12 business days and adds that to the created date which is incorrect.

Is there anyway to make the days convert to amount of time in a business day(which could be dynamic based on BusinessHours) instead of 5 business days being 5 24 hours days?

Heres the code we have currently:

Long interval = c.CreatedDate.addDays(Integer.valueOf(amountOfTimeString)).getTime() - c.CreatedDate.getTime();
c.SLA_Due_Date__c = BusinessHours.add(bh.Id, c.CreatedDate, interval);

I would wish to avoid dividing the interval by a magic number and have it instead be dynamic by the BusinessHours.

Any help would be great

BusinessHours API:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_businesshours.htm

Edit: adding complete method of snippet

private static Boolean setDate(Object amountOfTime, Object timeType, Case c, BusinessHours bh, SObject referenceObject) {
    Decimal amountOfTimeString = (Decimal) amountOfTime;
    String timeTypeString = (String) timeType;
    if(!String.isEmpty(String.valueOf(amountOfTimeString))) {
        if(timeTypeString == 'Business Hours') {
            Long interval = c.CreatedDate.addHours(Integer.valueOf(amountOfTimeString)).getTime() - c.CreatedDate.getTime(); 
            c.SLA_Due_Date__c = BusinessHours.add(bh.Id, c.CreatedDate, interval);
        } else if(timeTypeString == 'Calendar Hours') {
            c.SLA_Due_Date__c = c.CreatedDate.addHours(Integer.valueOf(amountOfTimeString));
        } else if(timeTypeString == 'Business Days') {
            System.debug('Amount of time string: ' + amountOfTimeString);
            Long interval = c.CreatedDate.addDays(Integer.valueOf(amountOfTimeString)).getTime() - c.CreatedDate.getTime();
            System.debug('Created Date: ' + c.CreatedDate);
            c.SLA_Due_Date__c = BusinessHours.add(bh.Id, c.CreatedDate, interval);
        } else if(timeTypeString == 'Calendar Days') {
             c.SLA_Due_Date__c = c.CreatedDate.addDays(Integer.valueOf(amountOfTimeString));
        }

        return true;
    }
    return false;
}

Best Answer

It might be more clear to calculate the diff you want algebraically. If you want 10 hours per day, and you have an Integer that represents how many days you want to add, then you need to add:

Long days = 30;
Long interval = days * 10 * 60 * 60 * 1000;
//                 d    h    m    s     ms

What you have done is add 24 hours per day. It would be equivalent to

Long days = 30;
Long interval = days * 24 * 60 * 60 * 1000;
//                 d    h    m    s     ms

If you want it to be more dynamic, you can try an iterative approach. Something like:

public static Datetime addBusinessDays(Datetime pointer, Integer days)
{
    Integer elapsed = 0;
    while (elapsed < days)
    {
        pointer = pointer.addDays(1);
        if (BusinessHours.isWithin(bh.Id, pointer)) elapsed++;
        else pointer = BusinessHours.nextStartDate(bh.Id);
    }
    return pointer;
}
Related Topic