【问题标题】:calculating sla based on minutes on working hours and business days根据工作时间和工作日的分钟数计算 SLA
【发布时间】:2020-07-19 02:25:30
【问题描述】:

我正在尝试构建一个函数,该函数根据工作时间计算票证 SLA,并跳过非工作时间和周末的计算,并将时间相应地转移到第二天或下一个工作日。我对工单的响应 SLA​​ 是 30 分钟,如果工单插入日期在工作日 {Mon-Fri} 和营业时间 {08:00:00 - 17:00:00} 内,那么我的结束日期应根据以下计算因素:

  1. 对于周一到周四,如果 insertDate 在工作时间之内,时间应该转移到工作时间的下一个 30 分钟,例如如果 案例1:插入日期='2020-07-16 16:00:00';在这里,我得到了预期的结果,endDate ='2020-07-16 16:30:00'; 如果 insertDate 时间戳超过工作时间窗口,例如如果 案例2:插入日期='2020-07-16 16:50:00';在这里,我没有得到预期的结果,应该是 endDate ='2020-07-17 08:20:00';
  2. 对于周末(周六到周日),在这个周末窗口创建的任何票,计算应该从周一开始,从 08:00:00 开始 案例3:插入日期='2020-07-18 16:50:00';在这里,我没有得到预期的结果,应该是 endDate ='2020-07-20 08:30:00';

下面是我的代码,它适用于 case1 很好,ubt 中断了 case2 和 case3,对此的任何帮助都非常感谢。

<?php
function calculateSLA($totalMinutes){
$insertDate = '2020-07-16 16:00:00';
$endDate = date('Y-m-d H:00:00',strtotime($insertDate)); 
//$t_min = date('i',strtotime($insertDate));
$BusinessStart = '08:00:00';
$BusinessEnd   = '17:00:00';
$i           = 1;
$flag        = false;

while ($totalMinutes > 0) {
    $day = date('D', strtotime($endDate)); // fetching day of week
    if ($day == 'Sat') { // checking if saturday thenskip by adding 2 day to end date
        $endDate = date('Y-m-d', strtotime($endDate . " +2 Day")) . ' ' . $BusinessStart; // adding 2 day if saturday
        continue;
    }
    $diff  = strtotime($BusinessEnd) - strtotime(date("H:i:s", strtotime($insertDate))); // getting difference of time of office end date and result end date
    var_dump($diff);
    $mins = $diff / (60); // difference in mins.
    if ($mins > $totalMinutes) {
        $mins = $totalMinutes;
        $flag  = true; 
    } else {
        $mins = $totalMinutes - $mins; // substracting mins from total minutes left
        
    }
    $endDate = date('Y-m-d H:i:s', strtotime("+$mins Minute", strtotime($insertDate))); // adding subtracted minutes
    if (!$flag) {
        $endDate = date('Y-m-d', strtotime($insertDate . " +1 Day")) . ' ' . $BusinessStart; // if not last loop add day to result end date
    } else {
        break;
    }
}
echo $endDate;
}
calculateSLA(30);

?>

【问题讨论】:

    标签: php


    【解决方案1】:

    我将发布我的函数版本。您传递工单提交的 DateTime 并获取允许响应的 DateTime。

    function calculateSLA(DateTime $reportDate): DateTime {
      $responseDate = (clone $reportDate);
    
      // check conditions and add 1 minute to provided date 30 times (so 30 minutes)
      for($i=0; $i<30;$i++) {
        // if time is before 8:00 (working hours) skip to 8:00
        if ($responseDate->format('G') < 8) {
          $responseDate->setTime(8, 0);
        }
    
        // if time is after 17:00 (working hours) skip to next day at 8:00
        if ($responseDate->format('G') >= 17) {
          $responseDate->add(new DateInterval('PT15H'));
          $responseDate->setTime(8, 0);
        }
    
        // if at any time it is weekend skip to monday at 8:00
        if (in_array($responseDate->format('D'), ['Sat', 'Sun'])) {
          $responseDate = $responseDate->modify('next monday 8:00');
        }
    
        $responseDate->add(new DateInterval('PT1M'));
      }
    
      return $responseDate;
    }
    

    以及我用来在不同条件下测试此功能的代码:

    function test(string $date, string $expected) {
      $result = calculateSLA(new DateTime($date));
      echo 'date: '.$date.', expected: '.$expected.', got: '.$result->format('Y-m-d H:i:s').' '.($result->format('Y-m-d H:i:s') === $expected ? 'OK' : 'ERRROR').PHP_EOL;
    }
    test('2020-07-16 16:00:00', '2020-07-16 16:30:00'); // weekday during hours
    test('2020-07-16 16:50:00', '2020-07-17 08:20:00'); // weekday during hours until next day
    test('2020-07-18 16:50:00', '2020-07-20 08:30:00'); // weekend
    test('2020-07-16 06:50:00', '2020-07-16 08:30:00'); // weekday before working hours
    test('2020-07-16 20:50:00', '2020-07-17 08:30:00'); // weekday after working hours
    test('2020-07-17 16:50:00', '2020-07-20 08:20:00'); // friday during working hours until monday
    test('2020-07-17 17:50:00', '2020-07-20 08:30:00'); // friday after hours
    

    输出:

    date: 2020-07-16 16:00:00, expected: 2020-07-16 16:30:00, got: 2020-07-16 16:30:00 OK
    date: 2020-07-16 16:50:00, expected: 2020-07-17 08:20:00, got: 2020-07-17 08:20:00 OK
    date: 2020-07-18 16:50:00, expected: 2020-07-20 08:30:00, got: 2020-07-20 08:30:00 OK
    date: 2020-07-16 06:50:00, expected: 2020-07-16 08:30:00, got: 2020-07-16 08:30:00 OK
    date: 2020-07-16 20:50:00, expected: 2020-07-17 08:30:00, got: 2020-07-17 08:30:00 OK
    date: 2020-07-17 16:50:00, expected: 2020-07-20 08:20:00, got: 2020-07-20 08:20:00 OK
    date: 2020-07-17 17:50:00, expected: 2020-07-20 08:30:00, got: 2020-07-20 08:30:00 OK
    

    棘手的部分是星期五,你没有真正提到,但我为它添加了测试用例。

    【讨论】:

    • 非常感谢 blahy 的回复,为了计算回复日期,传递了两个参数,一个是日期,另一个是预期的。由于我只有 reportDate 作为输入,而预期日期应该是这个计算的输出,我为什么要在调用函数时将预期日期作为第二个参数传递?我的意思是该函数应该能够在调用为 calculateSLA($reportDate) 时返回预期日期,或者我在这里遗漏了什么,再次感谢您的帮助:)
    • 你只需要一个函数function calculateSLA(DateTime $reportDate): DateTime你通过了提交工单的日期,你得到了最大响应时间的日期(所以30分钟后)。 Rest(测试函数和下面的调用)只是为了测试这个函数是否正常工作。我将编辑答案以使其更清楚。
    • 谢谢 Blahy,我的错误是我在调用函数时忘记了新构造。它工作正常,符合预期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2016-12-19
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    相关资源
    最近更新 更多