多个记录的时间戳操作

时间:2016-12-06 14:51:27

标签: php mysql

我正在尝试计算每个用户的小时数。一个用户每天可以多次登记和退房。

除了CHECK IN和CHECK OUT之外,我还有两个(商业和私人)。

如果用户在同一天的最后一次CHECK OUT和最后一次CHECK IN之间有一个事件BUSINESS,则最后一次CHECK OUT和CHECK IN之间的时间将被视为工作时间。

如果他在CHECK OUT之后有一个BUSINESS事件作为最后一条记录,它将计算小时数(CHECK OUT时间 - CHECK IN + BUSINESS = 8)。

在表格中,我有为每个用户记录事件的地方。

案例1

ID       USERID             TIME               COMMAND

1         1          2016-11-29 08:00:00       CHECK_IN
2         1          2016-11-29 10:05:14       CHECK_OUT
3         1          2016-11-29 12:22:14       BUSINESS
4         1          2016-11-29 13:32:14       CHECK_IN
5         1          2016-11-29 16:00:00       CHECK_OUT

根据上表,我应该让该用户在特定日期共有8个工作小时。

案例2

ID       USERID             TIME               COMMAND

1         1          2016-11-29 08:00:00       CHECK_IN
2         1          2016-11-29 10:05:14       CHECK_OUT
3         1          2016-11-29 12:22:14       PRIVATE
4         1          2016-11-29 13:32:14       CHECK_IN
5         1          2016-11-29 16:00:00       CHECK_OUT

如果上一次结账(ID 2)和最后一次登记(ID 3)之间的时间不计入工作时间。

我正在尝试制作脚本来计算每个月每个员工的工作时间。

我在如何使用最接近的CHECK_IN减去CHECK_OUT时间时遇到问题,当用户有一天的多条记录时会出现此问题。

1 个答案:

答案 0 :(得分:2)

我正在做以下假设:

  • 工作小时数从未跨过日历日
  • 当天的第一张记录始终为CHECK_IN,除非当天的唯一记录为BUSINESS或PRIVATE
  • CHECK_IN记录后面总是有一条CHECK_OUT记录,而CHECK_IN和下一个CHECK_OUT之间没有其他记录
  • CHECK_OUT和下一个CHECK_IN之间只能有商业记录或私人记录(或两者都没有)。不可能两者兼得。
  • 我忽略了任何潜在的夏令时影响
  • 我假设$ entries是一个包含一天用户行数的数组
function getTimeWorkedFromEntries($entries)
{
    $timeWorked = 0;
    $lastTimeIn = null;
    $lastTimeOut = null;
    $lastEntry = null;

    // the case where the only entry that day is 'BUSINESS'
    if(count($entries) == 1 && $entries[0]['COMMAND'] == 'BUSINESS')
    {
        $timeWorked = 28800; // 8 hours
    }
    else
    {
        foreach($entries as $timeEntry)
        {
            // first check_in of the day
            if($timeEntry['COMMAND'] == 'CHECK_IN' && is_null($lastTimeOut))
            {
                $lastTimeIn = $timeEntry['TIME'];
            }
            // CHECK_IN following a CHECK_OUT and then a BUSINESS
            else if($timeEntry['COMMAND'] == 'CHECK_IN' && !is_null($lastTimeOut) && $lastEntry['COMMAND'] == 'BUSINESS')
            {
                $timeWorked += (strtotime($timeEntry['TIME']) - strtotime($lastTimeOut));
                $lastTimeIn = $timeEntry['TIME'];
            }
            else if($timeEntry['COMMAND'] == 'CHECK_IN')
            {
                $lastTimeIn = $timeEntry['TIME'];
            }
            // CHECK_OUT that follows a CHECK_IN
            else if($timeEntry['COMMAND'] == 'CHECK_OUT')
            {
                $timeWorked += (strtotime($timeEntry['TIME']) - strtotime($lastTimeIn));
                $lastTimeOut = $timeEntry['TIME'];
            }

            $lastEntry = $timeEntry;
        }
    }

    return $timeWorked;
}

Live Example