Search code examples
javadatetimesalesforcecalculatorapex

SLA expiration date calculation in Salesforce


How can I create Apex code that calculates an exact date/time after 72 hours of service from Monday to Friday from 8 am to 6 pm, and Saturdays from 8 am to 1 pm, taking into account holidays and using an initial date as a base? In other words, I need to provide the method with the start date and service hours so that it can calculate the final date.

I will provide two examples:

My initial date/time is 01/09/2023 08:00 am, and my service hours are 8, so my final date should be 01/09/2023 04:00 pm.

My initial date/time is 01/09/2023 08:00:00, and my service hours are 12, so my final date should be 02/09/2023 10:00:00. In this example, since my schedule is from Mon-Fri from 8 am to 6 pm, it skips to the 2nd day because on the 1st day, after 6 pm, it doesn't count until the next day, starting at 8 am.

I tried the following code, but it doesn't give me the expected results.

public class DateTimeCalculator {

    // Method to calculate the final date/time
    public static Datetime calculateFinalDatetime(Datetime initialDatetime, Integer serviceHours) {
        Integer dailyWorkHours = 8;
        Datetime finalDatetime = initialDatetime;
        List<Date> holidays = new List<Date>{Date.newInstance(2023, 9, 4)}; // List of holidays
        
        while (serviceHours > 0) {
            if (isWorkingDay(finalDatetime)) {
                Integer hoursUntilEndOfDay = (finalDatetime.addHours(18).getTime() - finalDatetime.getTime()) / 3600000;
                if (serviceHours <= hoursUntilEndOfDay) {
                    finalDatetime = finalDatetime.addHours(serviceHours);
                    serviceHours = 0;
                } else {
                    finalDatetime = finalDatetime.addHours(16); // Adjust to 8 am of the next day
                    finalDatetime = finalDatetime.addDays(1);
                    serviceHours -= hoursUntilEndOfDay;
                }
            } else {
                finalDatetime = finalDatetime.addHours(16); // Adjust to 8 am of the next day
                finalDatetime = finalDatetime.addDays(1);
            }
        }
        
        return finalDatetime;
    }

    // Method to check if a day is a working day
    private static Boolean isWorkingDay(Datetime day) {
        // Define working days (Monday to Friday) and Saturdays
        return (day.format('E') != 'Sat' && day.format('E') != 'Sun') ||
               (day.format('E') == 'Sat' && day.hour() >= 8 && day.hour() < 13);
    }
}

Solution

  • There's a better way, built-in method that does this calculation including weekends, holidays, daylight saving time...

    Go to Setup -> Business Hours. Configure your opening times and couple public holidays. Then read up about https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_classes_businesshours.htm or search questions about it like https://stackoverflow.com/a/69723001/313628 and https://stackoverflow.com/a/75553533/313628.