1

我用 PHP 编写了一个程序,它在工作时存储在 MySQL 数据库中。显示程序是否正常工作的表格如下所示:

Table_name: downtime
Working(int)    Time(datetime)
1               2011-05-06 15:18:55
0               2011-05-06 15:20:21
1               2011-05-06 15:20:24
0               2011-05-06 16:05:13
1               2011-05-06 16:05:15
0               2011-05-06 16:27:59
1               2011-05-06 16:28:01
0               2011-05-06 16:37:35
1               2011-05-06 16:37:37

现在我想检索日期之间的“停机时间”。假设日期 1 是 2011-05-06 15:20:24,日期 2 是 2011-05-06 16:28:15,那么我希望脚本返回该期间 1 和 0 之间差异的总和. 我怎样才能做到这一点?

重要的是要知道日期 1 例如何时是 2011-05-06 15:20:22,然后有两秒的额外停机时间。很难想出一个(几乎)完美的解决方案。

4

5 回答 5

2

这段代码应该可以工作,我已经用你的示例数据对其进行了测试:

// Example data
// Note: assumes $data is sorted by date already
$data = array(
    "2011-05-06 15:18:55"=>1,
    "2011-05-06 15:20:21"=>0,
    "2011-05-06 15:20:24"=>0,
    "2011-05-06 16:05:13"=>0,
    "2011-05-06 16:05:15"=>0,
    "2011-05-06 16:27:59"=>1,
    "2011-05-06 16:28:01"=>0,
    "2011-05-06 16:37:35"=>0,
    "2011-05-06 16:37:37"=>1
    );

$startTime = strtotime("2011-05-06 15:18:55");
$endTime = strtotime("2011-05-06 16:28:01");

$totalUptime = 0;    
$lastUptime = 0;

foreach ($data as $dateString => $isWorking)
{
    $timestamp = strtotime($dateString);

    if ($lastWorking && $lastTimestamp)
    {
        $allowedStart = $lastTimestamp;
        if ($allowedStart<$startTime)
            $allowedStart = $startTime;

        $allowedEnd = $timestamp;
        if ($allowedEnd>$endTime)
            $allowedEnd = $endTime;

        $diff = $allowedEnd-$allowedStart;

        if ($diff>0)
        {
            $totalUptime += $diff;
        }
    }

    if ($timestamp>=$endTime)
    {
        break;
    }

    $lastTimestamp = $timestamp;    
    $lastWorking = $isWorking;
}

print "Total uptime: ".$totalUptime." seconds";

您只需$data要从数据库中填充您自己的记录。

于 2011-05-06T17:34:38.200 回答
1

使用strtotime()遍历所有将时间戳转换为 unix 纪元的行,然后找出它们之间的差异,并将其相加以获得总停机时间。

于 2011-05-06T16:55:19.283 回答
1

我现在使用的解决方案如下:

    $objects = Get("table","`date` BETWEEN '".$date_start."' AND '".$date_end."'");   

    $prev = new stdClass();
    $prev->new = 1;
    $prev->date = $date_start;

    $next = new stdClass();
    $next->new = 0;
    $next->date = $date_end;
    $objects = array_merge(array($prev),$objects,array($next));

    $uptime = 0;
    $downtime = 0;
    $prevtime = false;
    foreach($objects as $object)
    {
        $newtime = strtotime($object->date);
        if($prevtime && $object->new == 1)
        {
            $downtime += $newtime - $prevtime;
        }
        elseif($prevtime && $object->new == 0)
        {
            $uptime += $newtime - $prevtime;
        }
        $prevtime = $newtime;
    }     

得到(); 是我与数据库通信的函数:它返回查询找到的对象(记录),如果您想测试/使用此代码,请将其替换为以下内容:

$objects = array();
$result = mysql_query("SELECT * FROM table WHERE `date` BETWEEN '".$date_start."' AND '".$date_end."'");
while($object = mysql_fetch_object($result))
{
    $objects[] = $object;    
}
于 2011-05-08T00:02:05.457 回答
0
select timediff(
(
    select `time`
    from downtime
    where working = 1
    and `time` > t1.`time`
    order by `time` asc
    limit 1
),
t1.`time`
)
from downtime t1
where t1.working = 0

这应该为您提供几行,每个停机时间段。每行显示一个时间差,您仍然需要将这些行加在一起才能找到实际的停机时间。我不确定当您使用 MySQL 的 sum() 函数处理时差时会发生什么,它可能只返回秒数。您可以根据需要限制该time字段,尽管我尚未测试开始时间或结束时间处于停机时间时会发生什么。

于 2011-05-06T17:23:00.000 回答
-1

编辑:我误解了这个问题,忽略这个答案

答案很大程度上取决于您如何在 MySQL 中存储这些数据。您很可能需要这样的查询:

SELECT COUNT(*) FROM table WHERE working='1' AND DATE>='startDate' AND DATE<='endDate';

这将为您提供给定范围内“1”的数量。

于 2011-05-06T16:48:52.220 回答