0

I have written the following code . But it's not giving result nor any error. My requirement is to add 3 days to CreatedDate, excluding weekend and holidays.

Datetime createdDate = system.now();

Datetime dueDate = createdDate.addDays(3);

Integer holidaysCount = 0;
BusinessHours bh;

List<BusinessHours> temp = [SELECT ID, Name, IsDefault, IsActive From BusinessHours 
                WHERE IsDefault = true ];

for (BusinessHours b : temp) {
    if (b.IsDefault) {
        bh = b;
    }
}

while (createdDate != dueDate) {

    Datetime now = Datetime.newInstance(createdDate.year(), createdDate.month(), createdDate.day(), 0, 0, 0);
    Boolean isHoliday = !BusinessHours.isWithin(bh.Id, now);

    if ((isHoliday) || createdDate.format('E') == 'Sat' || createdDate.format('E') == 'Sun') {
        createdDate = createdDate.addDays(1);
    }
}    
0

3 Answers 3

4

You're doing more work than you have to in a lot of this code, but the core issue is your approach itself. You should create an Integer counter variable for the number of days elapsed, then increment a Datetime pointer.

You also seem to have a fundamental misunderstanding about how the BusinessHours class works. You don't need to check for yourself if the day is a weekend, that's the job of your hours definition in the first place. If you specify hours for Monday-Friday and none on Saturday or Sunday, then the isWithin method will always return false on those weekend days. It doesn't just check holidays.

Here's how I would write a utility class to calculate business days:

public class BusinessDays
{
    public static BusinessHours defaultHours
    {
        get
        {
            if (defaultHours == null)
                defaultHours = [SELECT Id FROM BusinessHours WHERE IsDefault = true];
            return defaultHours;
        }
        private set;
    }

    public static Datetime add(Datetime pointer, Integer days)
    {
        pointer = BusinessHours.nextStartDate(defaultHours.Id, pointer);
        // make sure you're starting at a Datetime within BusinessHours

        for (Integer elapsed = 0; elapsed < days; elapsed++)
        {
            pointer = pointer.addDays(1);
            if (!BusinessHours.isWithin(defaultHours.Id, pointer))
                pointer = BusinessHours.nextStartDate(defaultHours.Id, pointer);
        }
        return pointer;
    }
}

Then your code would simplify to:

Datetime dueDate = BusinessDays.add(createdDate, 3);

Note that the output is in GMT, so you may need to adjust it to include timezone offsets.

1
Datetime createdDate = system.now();

Datetime dueDate = createdDate.addDays(3);

Integer holidaysCount = 0;

BusinessHours bh = [SELECT ID, Name, IsDefault, IsActive From BusinessHours 
                WHERE IsDefault = true LIMIT 1];

Integer nbDaysAdded = 0;
while (nbDaysAdded != 3) {
    Datetime now = Datetime.newInstance(createdDate.year(), createdDate.month(), createdDate.day(), 0, 0, 0);
    Boolean isHoliday = !BusinessHours.isWithin(bh.Id, now);

    if(((isHoliday) || createdDate.format('E') == 'Sat' || createdDate.format('E') == 'Sun') == false){
       nbDaysAdded++;
    }
    createdDate = createdDate.addDays(1);
}    
0

There is already a method for this in BusinessHours class. If your Business Hours is excluding weekends and holidays then it will be very easy to calculate required datetime.

BusinessHours.add(businessHoursId, startDate, intervalMilliseconds)

So your code will look like this;

Datetime createdDate = system.now();
BusinessHours bh = [SELECT ID, Name, IsDefault, IsActive From BusinessHours WHERE IsDefault = true ];
Datetime dueDate = BusinessHours.add(bh.Id, createdDate, 3*24*60*1000); //last parameter is 3 days in milliseconds
1
  • 4
    24 business hours != 1 business day.
    – Adrian Larson
    Commented Jan 9, 2017 at 18:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .