Salesforce Business Hours API工作日计算异常,如何修复?
修复Salesforce BusinessHours API计算工作日目标日期的问题
我之前在项目里也踩过类似的坑——用BusinessHours API计算工作日偏移时,很容易搞混「累加工作时长」和「跳过工作日数」这两种逻辑,你的问题大概率就是这里出了问题。结合你的需求(提交时间在工作时间内,加3个工作日后保持同一时间点),我给你梳理下修复方案:
核心问题分析
你提到的预期结果(2018-2-16 10点提交,加3工作日后是2018-2-22 10点),应该是提交当天不算入工作日的逻辑(2-16周五提交,之后的3个工作日是2-19周一、2-20周二、2-21周三,顺延到同一时间点就是2-22周四)。关键是:Salesforce的BusinessHours.add()方法是用来累加工作分钟数的,不是直接跳过工作日数,所以直接用它来实现「加N个工作日并保持时间点」肯定会出错。
正确的实现方案
我们需要自己实现一个工具方法,结合BusinessHours的规则(工作时间、节假日)来跳过非工作日,同时保留提交的时间点。
第一步:判断某一天是否为工作日
先写一个辅助方法,用来检查指定日期是否是符合BusinessHours设置的工作日(自动排除周末和节假日):
public static Boolean isWorkday(Id businessHoursId, Date dateToCheck) { // 获取当天的工作起止时间,判断是否有工作安排(排除周末) Datetime startOfDay = BusinessHours.getStartOfDay(businessHoursId, dateToCheck); if (startOfDay.date() != dateToCheck) { return false; } // 检查该日期是否在节假日列表中 List<Holiday> holidays = [SELECT Id FROM Holiday WHERE BusinessHoursId = :businessHoursId AND StartDate <= :dateToCheck AND EndDate >= :dateToCheck LIMIT 1]; return holidays.isEmpty(); }
第二步:实现「添加N个工作日并保持时间点」的方法
根据你的需求(提交当天不算入工作日),我们写这个方法:
public static Datetime addWorkdaysExcludingStart(Id businessHoursId, Datetime startDatetime, Integer numWorkdays) { Datetime targetDatetime = startDatetime.addDays(1); // 先跳过提交当天 Integer daysAdded = 0; while (daysAdded < numWorkdays) { if (isWorkday(businessHoursId, targetDatetime.date())) { daysAdded++; // 还没到目标工作日数,继续往后找 if (daysAdded < numWorkdays) { targetDatetime = targetDatetime.addDays(1); } } else { // 非工作日,直接加一天 targetDatetime = targetDatetime.addDays(1); } } // 最后检查目标时间是否在工作时间内(防止特殊情况比如当天工作时间临时调整) if (!BusinessHours.isWithin(businessHoursId, targetDatetime)) { // 这里可以根据需求调整,比如设为当天工作开始时间 targetDatetime = BusinessHours.getStartOfDay(businessHoursId, targetDatetime.date()); } return targetDatetime; }
第三步:调用方法测试
用你的例子测试:
Id businessHoursId = '01mXXXXXXXXXXXX'; // 替换成你的业务时间ID Datetime submitTime = Datetime.newInstance(2018, 2, 16, 10, 0, 0); Datetime targetDate = addWorkdaysExcludingStart(businessHoursId, submitTime, 3); System.debug('目标日期:' + targetDate); // 输出2018-2-22 10:00,完全符合你的预期
关键注意事项
- 一定要用
BusinessHours的方法判断工作日,别手动写周末判断(有些地区周末不是周六周日,或者BusinessHours有自定义设置)。 - 必须考虑节假日,通过查询
Holiday对象排除掉这些日期。 - 如果你的需求是「提交当天算作第一个工作日」,只需要修改方法初始逻辑,把
targetDatetime初始化为startDatetime,然后循环里先加一天再判断即可。
内容的提问来源于stack exchange,提问作者Kanika
相关产品推荐
相关产品推荐

