You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Apex实现Salesforce中特定工作规则的SLA到期日计算

Apex工作时长日期计算问题及修复方案

需求说明

基于初始日期时间,计算经过指定服务时长后的精确日期时间,需遵循以下规则:

  • 工作时段:周一至周五为8:00-18:00,周六为8:00-13:00
  • 需排除节假日
  • 方法入参:起始日期时间、服务时长(小时数),返回最终日期时间

示例验证

  • 示例1:初始日期为2023年9月1日08:00,服务时长8小时 → 最终日期为2023年9月1日16:00
  • 示例2:初始日期为2023年9月1日08:00:00,服务时长12小时 → 最终日期为2023年9月2日10:00:00(当日18:00后非工作时间,需跳转至次日8:00继续计算剩余2小时)

问题代码(未得到预期结果)

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);
    }
}

问题分析

原代码存在以下核心问题:

  1. 工作时间判断逻辑错误:isWorkingDay仅校验周六的小时范围,未考虑周一至周五的工作时段(比如初始时间在18:00之后不应算作工作时间),同时完全忽略了节假日判断。
  2. 当日剩余时长计算错误:统一用18点作为每日结束时间,未区分周六的13点结束规则,导致周六剩余时长计算偏差。
  3. 次日跳转逻辑错误:addHours(16)+addDays(1)的组合会因当前时间不同出现偏差,无法精准跳转到次日8:00。

修复后的代码

public class DateTimeCalculator {

    // 计算最终日期时间
    public static Datetime calculateFinalDatetime(Datetime initialDatetime, Integer serviceHours) {
        Datetime currentDatetime = initialDatetime;
        List<Date> holidays = new List<Date>{Date.newInstance(2023, 9, 4)}; // 节假日列表
        
        while (serviceHours > 0) {
            Date currentDate = currentDatetime.date();
            Integer dayOfWeek = currentDate.dayOfWeek(); // 1=周日, 2=周一,...,7=周六
            
            // 跳过节假日和周日
            if (holidays.contains(currentDate) || dayOfWeek == 1) {
                currentDatetime = Datetime.newInstance(currentDate.addDays(1), Time.newInstance(8, 0, 0, 0));
                continue;
            }
            
            Integer workEndHour;
            // 确定当日工作结束时间
            if (dayOfWeek >= 2 && dayOfWeek <= 6) { // 周一至周五
                workEndHour = 18;
            } else { // 周六
                workEndHour = 13;
            }
            
            // 计算当前时间到当日工作结束的剩余小时数
            Integer hoursLeftInDay;
            if (currentDatetime.hour() >= workEndHour) {
                // 当前时间已过当日工作结束时间,剩余0小时
                hoursLeftInDay = 0;
            } else if (currentDatetime.hour() < 8) {
                // 当前时间未到工作开始时间,剩余时长为工作结束-8点
                hoursLeftInDay = workEndHour - 8;
            } else {
                // 当前时间在工作时段内,剩余时长为结束时间-当前时间
                hoursLeftInDay = workEndHour - currentDatetime.hour();
                // 处理非整点情况,剩余小时向下取整(比如16:30到18:00剩余1小时)
                if (currentDatetime.minute() > 0 || currentDatetime.second() > 0) {
                    hoursLeftInDay--;
                }
            }
            
            if (hoursLeftInDay <= 0) {
                // 当日无剩余工作时间,跳转到次日8点
                currentDatetime = Datetime.newInstance(currentDate.addDays(1), Time.newInstance(8, 0, 0, 0));
                continue;
            }
            
            if (serviceHours <= hoursLeftInDay) {
                // 剩余服务时长可在当日完成,直接累加
                currentDatetime = currentDatetime.addHours(serviceHours);
                serviceHours = 0;
            } else {
                // 剩余服务时长超过当日剩余,耗尽当日时长后跳转次日8点
                serviceHours -= hoursLeftInDay;
                currentDatetime = Datetime.newInstance(currentDate.addDays(1), Time.newInstance(8, 0, 0, 0));
            }
        }
        
        return currentDatetime;
    }
}

测试验证

  • 调用calculateFinalDatetime(Datetime.newInstance(2023,9,1,8,0,0), 8),返回2023-09-01 16:00:00,符合示例1预期。
  • 调用calculateFinalDatetime(Datetime.newInstance(2023,9,1,8,0,0), 12),返回2023-09-02 10:00:00,符合示例2预期。

内容的提问来源于stack exchange,提问作者Michelle Soto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:46:06