Calculate business days in PHP

strtotime 是 PHP 里面一个非常强大的函数,能将(几乎)任何(英文)字符串的日期时间描述解析为 Unix 时间戳.(Parse about any English textual datetime description into a Unix timestamp)

这里插一句题外话,请大家注意中文文档的 “任何字符串的日期时间” 和英文文档 “about any English textual datetime description” 在描述上的偏差。所以技术文档尽可能还是看官方的英文文档吧。

回归正题,strtotime 到底有多好用呢?比如要计算 3 Days Later,我以前是这样写的。

echo date('Y-m-d H:i:s', time() + 3*24*60*60);

用 strtotime 就可以直接写 “+3 days”,简洁明了,还解决了让人头疼的夏令时的问题。

echo date('Y-m-d H:i:s', strtotime('+3 days'));

你甚至可以写我记得那是去年五月份的最后一个礼拜天, 午后三点的阳光刚刚好。(虽然实际上你根本不需要做这种计算)

echo date('Y-m-d H:i:s', strtotime('last year, last sunday of may, 3 pm'));

是不是很好用?


当然 strtotime 也不是万能的,比如我要计算 7 个工作日之后的时候, 尝试了 strtotime(‘+7 business days’) 和 strtotime(‘+7 working days’) 都是返回 false.

echo date('Y-m-d H:i:s', strtotime('+7 business days'));
echo date('Y-m-d H:i:s', strtotime('+7 working days'));

为什么 strtomtime 不能做 “Business Day” 或者 “Working Day” 的相关计算呢?我猜测可能并不是每个地方都是周一到周五工作,周六周末休息,没有统一的,明确的关于 “工作日” 的定义,考虑到代码的严谨性,所以也就没有实现相关的功能。但是老板可不愿意听这些解释,所以我们今天主要来看一下怎么用 PHP 做 “工作日” 相关的计算吧。

首先想到的一个思路是 do-while 循环,从今天开始,如果是工作日,就记一天,如果是工作日就跳过,直到记满 7 天为止,代码如下。

$businessDays = 7;
$time = time();

do {
    $time = strtotime("+1 day", $time);
    if (in_array(date('w', $time), [1, 2, 3, 4, 5])) {
        $businessDays--;
    }
} while ($businessDays > 0);

echo date('Y-m-d', $time);

稍微抽象一下,其实我们要解决的就是把 + N Business Days 转化为 + N Days 的问题。比如今天是周一,那么 + 7 Business Days 就等于 + 9 Days, 以此类推。

function businessDays($businessDays) {
    $weeks = intval($businessDays / 5);
    $days = $businessDays % 5;

    if ($days + date('w') > 5) {
        $days += 2;
    }

    return $weeks * 7 + $days;
}

echo date('Y-m-d', strtotime('+' . businessDays('7') . ' days'));

这样的写法是不是逻辑会更清晰呢?今天就这样啦,如果感兴趣的话可以优化一下上面的函数,支持 – N Business Days, +/- N Business Days from specific date and time。


http://php.net/manual/en/function.strtotime.php

292 total views, no views today