PHP:时间戳按天,周,月,年分组

6l7fqoea  于 2023-01-01  发布在  PHP
关注(0)|答案(2)|浏览(263)

在我的应用程序中,我使用的是RRD,但在几个特定的场景中,我希望获取数据并对其进行分组(基于时间戳按天、周、月、年)。
下面是一个例子,可以让你更好地理解我:
我们有一个包含两个数据源的数组(all,active)。在每个数据源中,键是时间戳,时间戳之间的间隔是86400秒。

$arr = [
    "all" => [
        "1664236800" => 0,
        "1664323200" => 0,
        "1664409600" => 0,
        "1664496000" => 0,
        "1664582400" => 0,
        "1664668800" => 0,
        "1664755200" => 0,
        "1664841600" => 0,
        "1664928000" => 0,
        "1665014400" => 0,
        "1665100800" => 0,
        "1665187200" => 0,
        "1665273600" => 0,
        "1665360000" => 0,
        "1665446400" => 0,
        "1665532800" => 0,
        "1665619200" => 0,
        "1665705600" => 0,
        "1665792000" => 0,
        "1665878400" => 0,
        "1665964800" => 0,
        "1666051200" => 0,
        "1666137600" => 0,
        "1666224000" => 0,
        "1666310400" => 0,
        "1666396800" => 0,
        "1666483200" => 0,
        "1666569600" => 0,
        "1666656000" => 0,
        "1666742400" => 0,
        "1666828800" => 0,
        "1666915200" => 0,
        "1667001600" => 0,
        "1667088000" => 0,
        "1667174400" => 0,
        "1667260800" => 0,
        "1667347200" => 0,
        "1667433600" => 0,
        "1667520000" => 0,
        "1667606400" => 0,
        "1667692800" => 0,
        "1667779200" => 0,
        "1667865600" => 0,
        "1667952000" => 0,
        "1668038400" => 0,
        "1668124800" => 0,
        "1668211200" => 0,
        "1668297600" => 0,
        "1668384000" => 0,
        "1668470400" => 0,
        "1668556800" => 0,
        "1668643200" => 0,
        "1668729600" => 0,
        "1668816000" => 0,
        "1668902400" => 0,
        "1668988800" => 0,
        "1669075200" => 0,
        "1669161600" => 0,
        "1669248000" => 0,
        "1669334400" => 0,
        "1669420800" => 0,
        "1669507200" => 0,
        "1669593600" => 0,
        "1669680000" => 0,
        "1669766400" => 0,
        "1669852800" => 0,
        "1669939200" => 0,
        "1670025600" => 0,
        "1670112000" => 0,
        "1670198400" => 0,
        "1670284800" => 0,
        "1670371200" => 0,
        "1670457600" => 0,
        "1670544000" => 0,
        "1670630400" => 0,
        "1670716800" => 0,
        "1670803200" => 0,
        "1670889600" => 0,
        "1670976000" => 0,
        "1671062400" => 0,
        "1671148800" => 0,
        "1671235200" => 0,
        "1671321600" => 0,
        "1671408000" => 0,
        "1671494400" => 0,
        "1671580800" => 0,
        "1671667200" => 0,
        "1671753600" => 0,
        "1671840000" => 0,
        "1671926400" => 0,
        "1672012800" => 0,
        "1672099200" => 0,
        "1672185600" => 0,
        "1672272000" => 0,
    ],
    "active" => [
        "1664236800" => 0,
        "1664323200" => 0,
        "1664409600" => 0,
        "1664496000" => 0,
        "1664582400" => 0,
        "1664668800" => 0,
        "1664755200" => 0,
        "1664841600" => 0,
        "1664928000" => 0,
        "1665014400" => 0,
        "1665100800" => 0,
        "1665187200" => 0,
        "1665273600" => 0,
        "1665360000" => 0,
        "1665446400" => 0,
        "1665532800" => 0,
        "1665619200" => 0,
        "1665705600" => 0,
        "1665792000" => 0,
        "1665878400" => 0,
        "1665964800" => 0,
        "1666051200" => 0,
        "1666137600" => 0,
        "1666224000" => 0,
        "1666310400" => 0,
        "1666396800" => 0,
        "1666483200" => 0,
        "1666569600" => 0,
        "1666656000" => 0,
        "1666742400" => 0,
        "1666828800" => 0,
        "1666915200" => 0,
        "1667001600" => 0,
        "1667088000" => 0,
        "1667174400" => 0,
        "1667260800" => 0,
        "1667347200" => 0,
        "1667433600" => 0,
        "1667520000" => 0,
        "1667606400" => 0,
        "1667692800" => 0,
        "1667779200" => 0,
        "1667865600" => 0,
        "1667952000" => 0,
        "1668038400" => 0,
        "1668124800" => 0,
        "1668211200" => 0,
        "1668297600" => 0,
        "1668384000" => 0,
        "1668470400" => 0,
        "1668556800" => 0,
        "1668643200" => 0,
        "1668729600" => 0,
        "1668816000" => 0,
        "1668902400" => 0,
        "1668988800" => 0,
        "1669075200" => 0,
        "1669161600" => 0,
        "1669248000" => 0,
        "1669334400" => 0,
        "1669420800" => 0,
        "1669507200" => 0,
        "1669593600" => 0,
        "1669680000" => 0,
        "1669766400" => 0,
        "1669852800" => 0,
        "1669939200" => 0,
        "1670025600" => 0,
        "1670112000" => 0,
        "1670198400" => 0,
        "1670284800" => 0,
        "1670371200" => 0,
        "1670457600" => 0,
        "1670544000" => 0,
        "1670630400" => 0,
        "1670716800" => 0,
        "1670803200" => 0,
        "1670889600" => 0,
        "1670976000" => 0,
        "1671062400" => 0,
        "1671148800" => 0,
        "1671235200" => 0,
        "1671321600" => 0,
        "1671408000" => 0,
        "1671494400" => 0,
        "1671580800" => 0,
        "1671667200" => 0,
        "1671753600" => 0,
        "1671840000" => 0,
        "1671926400" => 0,
        "1672012800" => 0,
        "1672099200" => 0,
        "1672185600" => 0,
        "1672272000" => 0,
    ]
];

我想把这些数据按月份分组。
示例响应:

$arr = [
    "1664236800" => [ // 27 September ( this is first value from fetch array)
        "all" => [
            "1664236800" => 0,
            "1664323200" => 0,
            "1664409600" => 0,
            "1664496000" => 0,
        ],
        "active" => [
            "1664236800" => 0,
            "1664323200" => 0,
            "1664409600" => 0,
            "1664496000" => 0,
        ],
    ],
    "1664582400" => [ // 1st October
        "all" => [
            "1664582400" => 0,
            "1664668800" => 0,
            "1664755200" => 0,
            "1664841600" => 0,
            "1664928000" => 0,
            "1665014400" => 0,
            "1665100800" => 0,
            "1665187200" => 0,
            "1665273600" => 0,
            "1665360000" => 0,
            "1665446400" => 0,
            "1665532800" => 0,
            "1665619200" => 0,
            "1665705600" => 0,
            "1665792000" => 0,
            "1665878400" => 0,
            "1665964800" => 0,
            "1666051200" => 0,
            "1666137600" => 0,
            "1666224000" => 0,
            "1666310400" => 0,
            "1666396800" => 0,
            "1666483200" => 0,
            "1666569600" => 0,
            "1666656000" => 0,
            "1666742400" => 0,
            "1666828800" => 0,
            "1666915200" => 0,
            "1667001600" => 0,
            "1667088000" => 0,
            "1667174400" => 0,
        ],
        "active" => [
            "1664582400" => 0,
            "1664668800" => 0,
            "1664755200" => 0,
            "1664841600" => 0,
            "1664928000" => 0,
            "1665014400" => 0,
            "1665100800" => 0,
            "1665187200" => 0,
            "1665273600" => 0,
            "1665360000" => 0,
            "1665446400" => 0,
            "1665532800" => 0,
            "1665619200" => 0,
            "1665705600" => 0,
            "1665792000" => 0,
            "1665878400" => 0,
            "1665964800" => 0,
            "1666051200" => 0,
            "1666137600" => 0,
            "1666224000" => 0,
            "1666310400" => 0,
            "1666396800" => 0,
            "1666483200" => 0,
            "1666569600" => 0,
            "1666656000" => 0,
            "1666742400" => 0,
            "1666828800" => 0,
            "1666915200" => 0,
            "1667001600" => 0,
            "1667088000" => 0,
            "1667174400" => 0,
        ],
    ],
    "1667260800" => [ // 1st November
        "all" => [
            "1667260800" => 0,
            "1667347200" => 0,
            "1667433600" => 0,
            "1667520000" => 0,
            "1667606400" => 0,
            "1667692800" => 0,
            "1667779200" => 0,
            "1667865600" => 0,
            "1667952000" => 0,
            "1668038400" => 0,
            "1668124800" => 0,
            "1668211200" => 0,
            "1668297600" => 0,
            "1668384000" => 0,
            "1668470400" => 0,
            "1668556800" => 0,
            "1668643200" => 0,
            "1668729600" => 0,
            "1668816000" => 0,
            "1668902400" => 0,
            "1668988800" => 0,
            "1669075200" => 0,
            "1669161600" => 0,
            "1669248000" => 0,
            "1669334400" => 0,
            "1669420800" => 0,
            "1669507200" => 0,
            "1669593600" => 0,
            "1669680000" => 0,
            "1669766400" => 0,
        ],
        "active" => [
            "1667260800" => 0,
            "1667347200" => 0,
            "1667433600" => 0,
            "1667520000" => 0,
            "1667606400" => 0,
            "1667692800" => 0,
            "1667779200" => 0,
            "1667865600" => 0,
            "1667952000" => 0,
            "1668038400" => 0,
            "1668124800" => 0,
            "1668211200" => 0,
            "1668297600" => 0,
            "1668384000" => 0,
            "1668470400" => 0,
            "1668556800" => 0,
            "1668643200" => 0,
            "1668729600" => 0,
            "1668816000" => 0,
            "1668902400" => 0,
            "1668988800" => 0,
            "1669075200" => 0,
            "1669161600" => 0,
            "1669248000" => 0,
            "1669334400" => 0,
            "1669420800" => 0,
            "1669507200" => 0,
            "1669593600" => 0,
            "1669680000" => 0,
            "1669766400" => 0,
        ],
    ],
    "1669852800" => [ // 1st December
        "all" => [
            "1669852800" => 0,
            "1669939200" => 0,
            "1670025600" => 0,
            "1670112000" => 0,
            "1670198400" => 0,
            "1670284800" => 0,
            "1670371200" => 0,
            "1670457600" => 0,
            "1670544000" => 0,
            "1670630400" => 0,
            "1670716800" => 0,
            "1670803200" => 0,
            "1670889600" => 0,
            "1670976000" => 0,
            "1671062400" => 0,
            "1671148800" => 0,
            "1671235200" => 0,
            "1671321600" => 0,
            "1671408000" => 0,
            "1671494400" => 0,
            "1671580800" => 0,
            "1671667200" => 0,
            "1671753600" => 0,
            "1671840000" => 0,
            "1671926400" => 0,
            "1672012800" => 0,
            "1672099200" => 0,
            "1672185600" => 0,
            "1672272000" => 0,
        ],
        "active" => [
            "1669852800" => 0,
            "1669939200" => 0,
            "1670025600" => 0,
            "1670112000" => 0,
            "1670198400" => 0,
            "1670284800" => 0,
            "1670371200" => 0,
            "1670457600" => 0,
            "1670544000" => 0,
            "1670630400" => 0,
            "1670716800" => 0,
            "1670803200" => 0,
            "1670889600" => 0,
            "1670976000" => 0,
            "1671062400" => 0,
            "1671148800" => 0,
            "1671235200" => 0,
            "1671321600" => 0,
            "1671408000" => 0,
            "1671494400" => 0,
            "1671580800" => 0,
            "1671667200" => 0,
            "1671753600" => 0,
            "1671840000" => 0,
            "1671926400" => 0,
            "1672012800" => 0,
            "1672099200" => 0,
            "1672185600" => 0,
            "1672272000" => 0,
        ],
    ]
];

哪种方法最好?
我的方法是转换date("Y-d", $timestamp)中的每个时间戳,并按响应分组。(不知道效果如何)

nkoocmlb

nkoocmlb1#

最简单的方法是在原始数组上循环,并为每个时间戳计算正确的每月时间段:

$result = array();
foreach($arr as $type => $items)
{
    foreach($items as $timestamp => $value)
    {
        // compute first day of month
        $d = new DateTime();
        $d->setTimestamp(intval($timestamp)); // load timestamp into a DateTime object
        $d->setTimeZone(new DateTimeZone('UTC'));
        $d->setTime(0, 0, 0); // remove hours, minutes and seconds parts (if needed)
        $d->modify('first day of this month');
        $firstMonthTimestamp = strval($d->getTimestamp());
        
        // create result array structure the first time
        if(!array_key_exists($firstMonthTimestamp, $result)) $result[$firstMonthTimestamp] = array();
        if(!array_key_exists($type, $result[$firstMonthTimestamp])) $result[$firstMonthTimestamp][$type] = array();
        
        // append element to the month list
        $result[$firstMonthTimestamp][$type][$timestamp] = $value ;
    }
}

print_r($result);
n8ghc7c1

n8ghc7c12#

就像经常发生的那样,在你问完一个问题后,答案会突然出现在你的脑海里。
上述解决方案很好,但我需要能够按小时、天、周、月和年对这些数据进行分组
这是我经过几天思考后的解决方案。

$groupData = (new Grouper())->group(new GroupByMonth(), $arr);

Grouper.php

class Grouper
{
    public function group(GrouperInterface $service, $data)
    {
        $dataSources     = array_keys($data);
        $timestamps      = array_keys($data[$dataSources[0]]);
        $groupData       = [];

        $lastKey = null;
        foreach ($timestamps as $timestamp) {
            if ($service->isNewGroup($timestamp)) {
                $groupData[$timestamp] = array_fill_keys($dataSources, []);
                $lastKey = $timestamp;
            }

            foreach ($dataSources as $ds) {
                $groupData[$lastKey][$ds][$timestamp] = $data[$ds][$timestamp];
            }
        }

        return $groupData;
    }
}

GroupByMonth.php

class GroupByMonth implements GrouperInterface
{
    private int $endTimestamp = -1;

    public function isNewGroup(int $timestamp): bool
    {
        if ($this->endTimestamp >= $timestamp) {
            return false;
        }

        $this->endTimestamp = $this->calculateEndTimestamp($timestamp);

        return true;
    }

    private function calculateEndTimestamp(int $timestamp): int
    {
        list($year, $month) = explode('-', date('Y-n', $timestamp));

        $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

        $date = \DateTime::createFromFormat("Y-n-d H:i:s", "{$year}-{$month}-{$daysInMonth} 23:59:59");

        return $date->getTimestamp();
    }
}

对我来说,这是一个更好的解决方案,因为它允许我编写更多的分组功能

相关问题