php跨天请假计算,请DS帮忙看下

比如:2021-09-10 08:30 - 2021-09-11 18:00 这两天跨天如何精确得计算出小时;
比如:
2021-09-10 08:30 - 2021-09-11 18:00 总共请假16个小时
2021-09-10 08:30 - 2021-09-11 15:30 总共请假13.5个小时
依次类推;因为每次跨天计算的时候都是计算的24个小时时间在里面;现在一点思路都没有

阅读 2.8k
3 个回答

按双休, 每天工作8小时, 9点上班, 12点到13点休息, 18点下班, 半小时为单位, 不足半小时按半小时算, 大于半小时按1小时算. 大概写了一下, 算法可能还可以精简

<?php

class Work {
    public static $workDays = [1, 2, 3, 4, 5];

    public static $workTimes = [
        ['09:00:00', '12:00:00'],
        ['13:00:00', '18:00:00'],
    ];

    public static function getWorkHours($from, $to) {
        $times = static::getAvailableTimes($from, $to);
        $hours = $times / 3600;
        $hour  = floor($hours);
        if ($hours == $hour) {
            return $hours;
        }
        $half = $hours - $hour;
        $hour += $half > 0.5 ? 1 : 0.5;

        return $hour;
    }

    public static function getAvailableTimes($from, $to) {
        $tsFrom   = strtotime($from);
        $tsTo     = strtotime($to);
        $dateFrom = date('Y-m-d', $tsFrom);
        $dateTo   = date('Y-m-d', $tsTo);

        $date  = $dateFrom;
        $times = 0;
        while ($date <= $dateTo) {
            $day = date('N', strtotime($date));
            if (!in_array($day, static::$workDays)) {
                $date = date('Y-m-d', strtotime($date . ' +1day'));
                continue;
            }
            $begin = $date == $dateFrom ? date('H:i:00', $tsFrom) : static::$workTimes[0][0];
            $end   = $date == $dateTo ? date('H:i:00', $tsTo) : static::$workTimes[1][1];

            foreach (static::$workTimes as $v) {
                if ($begin > $v[1] || $end < $v[0]) {
                    continue;
                }
                $tmpBegin = $begin > $v[0] ? $begin : $v[0];
                $tmpEnd   = $end < $v[1] ? $end : $v[1];
                $times += strtotime("{$date} {$tmpEnd}") - strtotime("{$date} {$tmpBegin}");
            }

            $date = date('Y-m-d', strtotime($date . ' +1day'));
        }

        return $times;
    }
}

$from = '2021-09-09 08:30';
$to   = '2021-09-10 15:20';

var_dump(Work::getWorkHours($from, $to));
$start = '2021-09-10 08:30';
$end   = '2021-09-11 18:00';
$hours = (strtotime($end) - strtotime($start)) / 3600

天单独算不就完事了,跨天了就算一天总请假时长加上非一天的时长,这和你只算一天的也没区别吧。而且跨天还得考虑工作日和非工作日这种,其实就是先算日,再算具体某一天吧,相比之下如果你第一天也不是开始时间的话,应该也要单独计算。所以跨天的话就是算开始日,中间所有时长,结束日。就算二天+全天请假的时长。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进