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

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

问题描述:

I'm looking to count values from an array that contain a certain number. Basically, I'm looking to plot a graph os visits, and want to do it as 'morning', 'afternoon' and 'evening'. So I want to count times, such as 17:38 as 17, then count them so I can classify if visits were morning, afternoon or evening.

$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'];

Expected output from sample data:

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

我正在寻找从包含特定数字的数组中计算值。 基本上,我希望绘制一个图表浏览器,并希望将其作为“早晨”,“下午”和“晚上”。 所以我想计算次数,例如 17:38 code>作为 17 code>,然后计算它们,这样我就可以分类,如果访问是早上,下午或晚上。 p> \ n

  $ 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'] + $ count ['13'] + $ count ['14'] + $ count ['15'] + $ counts ['16']; 
 $ evening_counts = $ counts ['17']  + $计数['18'] + $ count ['19'] + $ count ['20'] + $ count ['21'] + $ count ['22'] + $ count ['23']; \  n  code>  pre> 
 
 

样本数据的预期输出: p>

  $ morning_counts = 1 
 $ afternoon_count = 3 
 $ evening_counts  = 2 
  code>  pre> 
  div>

You can do this by creating counter variables. We can then create ranges of time frames using range(). Then get the values before the : in the time string as the hour and then compare that against the range, if it's in the range, add 1 to the counter.

<?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>';

refs:

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

Simplest option:

$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

I think it's pretty ugly though. I'd usually recommend to work with DateTimes or DatePeriods instead of strings.

Being REALLY simplistic about it you could do this in a switch statement

<?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>";

Here comes another solution

<?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;
}

This should do it in just a few lines:

$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

Using preg_match you can get also the count of times.

$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) } 
*/

This is the first time I've ever used the "spaceship operator" aka "3-way-comparison operator" on a snippet that wasn't calling usort().

It is perfectly suited for this task because you want to generate three buckets for your time values.

The spaceship operator returns one of three different values: -1, 0, and 1. It's job is to compare two strings and decide if the value on the left is less than, equal to, or greater than the right side value -- it then returns the respective numeric value mentioned in my previous sentence.

To set up this unique comparison operator (available from php7+), we need to boil down the input numbers so that they can be correctly "bucketed".

Most people rush to explode() (and too often don't use the 3rd parameter (limit) to inform php that no more than 2 elements are desired). I do not, because I don't like to generate an array from a string just to capture a substring. Because the time values are predictably formatted, the best tool for the task will be substr($time, 0, 2), but closely followed by strstr($time, ':', true) and if you want to be tricky "$time[0]$time[1]".

I hope my inline comments will clear up any other confusions about my concise and powerful snippet. (Just 4 lines of working code!)

Code: (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]}
";   // Hours: 00:00 to 11:59 ->12hrs (calculates as: 0, 1)
echo "Afternoon Count: {$buckets[0]}
";  // 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)

Output:

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

How does the calculation process breakdown?

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

Breakdown from time values 0 to 23:

//  |--------------------------------------------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]