如何将一天中的时间分成 3 个桶:早上、下午和晚上?

How to separate times of day into 3 buckets: morning, afternoon, and evening?

我想计算包含特定数字的数组中的值。基本上,我想绘制一个图表 os 访问,并希望将其绘制为 'morning'、'afternoon' 和 'evening'。所以我想统计时间,比如 17:3817,然后统计它们,这样我就可以分类访问时间是上午、下午还是晚上。

$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");

$counts = array_count_values($time_array);
$morning_counts = $counts['09'] + $counts['10'] + $counts['11'];
$afternoon_counts = $counts['12'] + $counts['13'] + $counts['14'] + $counts['15'] + $counts['16'];
$evening_counts = $counts['17'] + $counts['18'] + $counts['19'] + $counts['20'] + $counts['21'] + $counts['22'] + $counts['23'];

示例数据的预期输出:

$morning_counts = 1
$afternoon_count = 3
$evening_counts = 2

最简单的选项:

$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
$times = [];
foreach ($time_array as $time) {
    $times[] = substr($time, 0, 2);
}

// Proceed with original code, but swap $time_array for $times

虽然我觉得它很丑。我通常建议使用 DateTimes 或 DatePeriods 而不是字符串。

您可以通过创建计数器变量来做到这一点。然后我们可以使用 range() 创建时间范围的范围。然后获取时间字符串中:之前的值作为小时,然后将其与范围进行比较,如果在范围内,则将计数器加1。

<?php
    $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");

    # create counter vars
    $mornCount = 0;
    $afternoonCount = 0;
    $eveCount = 0;

    # create range of times to compare against
    $mornRange = range(0, 11);
    $afternoonRange = range(12, 16);
    $eveRange = range(17, 23);

    foreach ($time_array as $time)
    {
        $compareTimeArr = explode(':', $time); # get first two chars of time
        $compareTime = $compareTimeArr[0];

        if (in_array($compareTime, $mornRange)) {
            $mornCount++;
        } elseif (in_array($compareTime, $afternoonRange)) {
            $afternoonCount++;
        } elseif (in_array($compareTime, $eveRange)) {
            $eveCount++;
        }
    }

    echo '<pre>'. print_r($mornCount,1) .'</pre>';
    echo '<pre>'. print_r($afternoonCount,1) .'</pre>';
    echo '<pre>'. print_r($eveCount,1) .'</pre>';

参考文献:

https://secure.php.net/manual/en/function.in-array.php

https://secure.php.net/manual/en/function.explode.php

https://secure.php.net/manual/en/function.range.php

关于它真的很简单,你可以在 switch 语句中做到这一点

<?php
$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");

$morn = 0;
$after = 0;
$eve = 0;
$other = 0;
foreach ($time_array as $time) {
    $t = explode(':',$time)[0];
    switch ($t) {
        case '09':
        case '10':
        case '11':
        case '12':
            $morn++;
            break;

        case '13':
        case '14':
        case '15':
        case '16':
            $after++;
            break;

        case '17':
        case '18':
        case '19':
        case '20':
        case '21':
        case '22':
        case '23':
            $eve++;
            break;
        default:
            $other++;
    }
}
echo "Morning = $morn<br>";
echo "Afternoon = $after<br>";
echo "Evening= $eve<br>";
echo "Other = $other<br>";

又一个解决方案来了

<?php
$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
$counts = countValues($time_array);
$morning_counts = $counts['09'] + $counts['10'] + $counts['11'] + $counts['12'];
$afternoon_counts = $counts['12'] + $counts['13'] + $counts['14'] + $counts['15'] + $counts['16'];
$evening_counts = $counts['17'] + $counts['18'] + $counts['19'] + $counts['20'] + $counts['21'] + $counts['22'] + $counts['23'] + $counts['24'];

var_dump($morning_counts, $afternoon_counts, $evening_counts);

function countValues($time_array) {
    $result = [];
    for ($i = 0; $i <= 23; $i++) {
        $key = ($i < 10) ? ('0' . $i) : (string) $i;
        $result[$key] = 0;
    }
    foreach ($time_array as $time) {
        $key = strstr($time, ':', true);
        $result[$key]++;
    }
    return $result;
}

只需几行即可完成:

$counts = array_reduce($time_array, function($counts, $time) {
  $hour = (int)substr($time, 0, 2);
  $moment = in_array($hour, range(9, 12)) ? 'morning' : (in_array($hour, range(13, 16)) ? 'afternoon' : 'evening');
  $counts[$moment]++;
  return $counts;
}, ['morning' => 0, 'afternoon' => 0, 'evening' => 0]);

Demo here

使用preg_match你也可以得到次数。

$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
function time_results($time_array){
    $result = array('morning_counts'=>0,'afternoon_counts'=>0,'evening_counts'=>0,'total'=>0);
    $result['total'] = count($time_array);
    foreach($time_array as $time){
        if(preg_match('/^(09|10|11|12)\:*/',$time)){
            $result['morning_counts'] += 1;
        }else if(preg_match('/^(13|14|15|16)\:*/',$time)){
            $result['afternoon_counts'] += 1;
        }else if(preg_match('/^(17|18|19|20|21|22|23|24)\:*/',$time)){
            $result['evening_counts'] += 1;
        }
    }
    return $result;
}

var_dump(time_results($time_array));
/*
result : array(4) { ["morning_counts"]=> int(1) ["afternoon_counts"]=> int(3) ["evening_counts"]=> int(2) ["total"]=> int(6) } 
*/

这是我第一次在没有调用 usort().

的片段上使用 "spaceship operator" 又名“三向比较运算符”

它非常适合这项任务,因为您想为您的时间值生成三个桶。

宇宙飞船运算符 returns 三个不同值之一:-101。它的工作是比较两个字符串并确定左边的值是 less thanequal to 还是 greater than 右边的值——然后 returns 相应的数字我上一句提到的价值。

要设置这个独特的比较运算符(可从 php7+ 获得),我们需要将输入数字归结为 "bucketed".

大多数人急于 explode()(并且经常不使用第 3 个参数(限制)来通知 php 不需要超过 2 个元素)。我不喜欢,因为我不喜欢从字符串生成数组只是为了捕获子字符串。因为时间值的格式是可预测的,所以完成任务的最佳工具是 substr($time, 0, 2),但紧随其后的是 strstr($time, ':', true),如果你想变得棘手 "$time[0]$time[1]".

我希望我的内联评论能够消除关于我简洁而强大的代码段的任何其他困惑。 (只需 4 行工作代码!)

代码:(Demo)

$time_array = ["17:45", "13:12", "09:29", "17:32", "16:49", "14:18"];

$buckets = array_fill_keys([-1, 0, 1], 0);  // initialize buckets with 0 values

foreach ($time_array as $time) {
    ++$buckets[(int)sqrt(substr($time, 0, 2) - 8) <=> 2];
    //                                            ^^^^^-- 3-way comparison versus 2 
    //                                       ^^^--------- subtract 8 from the two-digit number
    //                   ^^^^^^^^^^^^^^^^^^^------------- extract first two digits from time string
    //             ^^^^^^-------------------------------- get squareroot value
    //         ^^^^--------------------------------- convert to integer (truncate decimals)
}

echo "Morning Count: {$buckets[-1]}\n";   // Hours: 00:00 to 11:59 ->12hrs (calculates as: 0, 1)
echo "Afternoon Count: {$buckets[0]}\n";  // Hours: 12:00 to 16:59 -> 5hrs (calculates as: 2)
echo "Evening Count: {$buckets[1]}";      // Hours: 17:00 to 23:59 -> 7hrs (calculates as: 3, 4)

输出:

Morning Count: 1
Afternoon Count: 3
Evening Count: 2

计算过程如何细分?

foreach (range(0, 23) as $t) {
    $calc = (float)sqrt($t - 8);
    echo "$t: " , (int)$calc , " ... [float value from sqrt was: $calc]\n";
}

从时间值 023 的细分:

//  |--------------------------------------------input time value
//  v  v-----------------------------------------final calculated value
//                                       vvv-----before converted to integer value
    0: 0 ... [float value from sqrt was: NAN]
    1: 0 ... [float value from sqrt was: NAN]
    2: 0 ... [float value from sqrt was: NAN]
    3: 0 ... [float value from sqrt was: NAN]
    4: 0 ... [float value from sqrt was: NAN]
    5: 0 ... [float value from sqrt was: NAN]
    6: 0 ... [float value from sqrt was: NAN]
    7: 0 ... [float value from sqrt was: NAN]
    8: 0 ... [float value from sqrt was: 0]
    9: 1 ... [float value from sqrt was: 1]
    10: 1 ... [float value from sqrt was: 1.4142135623731]
    11: 1 ... [float value from sqrt was: 1.7320508075689]
    12: 2 ... [float value from sqrt was: 2]
    13: 2 ... [float value from sqrt was: 2.2360679774998]
    14: 2 ... [float value from sqrt was: 2.4494897427832]
    15: 2 ... [float value from sqrt was: 2.6457513110646]
    16: 2 ... [float value from sqrt was: 2.8284271247462]
    17: 3 ... [float value from sqrt was: 3]
    18: 3 ... [float value from sqrt was: 3.1622776601684]
    19: 3 ... [float value from sqrt was: 3.3166247903554]
    20: 3 ... [float value from sqrt was: 3.4641016151378]
    21: 3 ... [float value from sqrt was: 3.605551275464]
    22: 3 ... [float value from sqrt was: 3.7416573867739]
    23: 3 ... [float value from sqrt was: 3.8729833462074]