在迭代datePeriod时,如何包括今天



为什么今天从返回的值中排除?

SELECT DATE(created) AS reg_date,
       COUNT(*) AS user_reg_per_day
FROM users
WHERE created > (NOW() - INTERVAL 30 DAY)
GROUP BY reg_date

我的查询似乎很好,但是我使用以下PHP来填补空白:

function generate_calendar_days() {
    $end = date("Y-m-d");
    $today = strtotime($end);
    $start = strtotime("-30 day", $today);
    $start = date('Y-m-d', $start);
    $range = new DatePeriod(
        DateTime::createFromFormat('Y-m-d', $start),
        new DateInterval('P1D'),
        DateTime::createFromFormat('Y-m-d', $end));
    $filler = array();
    foreach($range as $date) {
        $d = $date->format('Y-m-d');
        $filler[$d] = 0;
    }
    return $filler;
}

我的猜测是$today不正确。

没有理由您的查询应排除当天的数据,除非您将数据写入此表有一些奇怪的方式。您可能没有看到它是因为您没有订购结果(即它在结果集的底部)?

它将给出30天前一天的部分结果。因此,您可以考虑修改某些情况:

SELECT DATE(created) AS reg_date,
       COUNT(*) AS user_reg_per_day
FROM users
WHERE created >= DATE(DATE_SUB(NOW(),INTERVAL 30 DAY))
GROUP BY reg_date
ORDER BY reg_date DESC

以下是对更新问题的评论,因为似乎问题在PHP代码中。

我不完全理解为什么您会将Strtotime功能与DateTime,DateInterval,DatePeriod混合在一起。很高兴看到您正在使用这些,因为许多开发人员都大为充分利用。

说我可能会将该功能重写为:

function generate_calendar_days($start = 'today', $days = 30, $days_in_past = true) {
    $dates = array();
    try {
        $current_day = new DateTime($start);  // time set to 00:00:00
    } catch (Exception $e) {
        echo ('Failed with: ' . $e->getMessage());
        return false;
    }
    $interval = new DateInterval('P1D');
    if (true === $days_in_past) {
        $interval->invert = 1; // make days step back in time
    }
    $range = new DatePeriod($current_day, $interval, $days);
    foreach($range as $date) {
        $dates[] = $date->format('Y-m-d');
    }
    return $dates;
}

请注意,在这里,我添加了参数以使您的功能更灵活。我也只返回一系列日期字符串,以使功能更具通用。您可以将如何与此功能范围之外的实现细节一起使用如何使用。

您可以轻松地在函数调用之外构建零填充的数组:

$calendar = array_fill_keys(generate_calendar_days(), 0);

您的句子很完美,实际上SELECT (NOW() - INTERVAL 30 DAY)返回2013-12-18 22:33:30。我试验了类似的奇数问题,这是因为我们的DDBB服务器的时间配置与Apache Server不同,并且避免了我们的奇怪结果。

检查服务器时间配置,(http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html)

您可以从PHP手册中的注释中看到人们遇到的麻烦,包括迭代DatePeriod的结束日期。建议那里有各种各样的修改可以帮助您解决这个问题,但是对于您的工作,您并不需要结束日期,因为您总是从当前日期开始固定的天数。

您可以使用DatePeriod构造函数的"复发"形式包括结束日期。

function generate_calendar_days(int $n): array
{
    $range = new DatePeriod(new DateTime("-$n day"), new DateInterval('P1D'), $n);
    foreach($range as $date) {
        $filler[$date->format('Y-m-d')] = 0;
    }
    return $filler;
}
$days = generate_calendar_days(30);

最新更新