如何在迭代DatePeriod时包括今天?

时间:2014-01-17 21:29:29

标签: php mysql sql

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

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不正确。

3 个答案:

答案 0 :(得分:1)

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

这将是30天前的一天的部分日结果。因此,您可以考虑稍微修改WHERE条件:

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);

答案 1 :(得分:0)

你的句子很完美,事实上SELECT (NOW() - INTERVAL 30 DAY)会返回2013-12-18 22:33:30。我尝试了类似的奇怪问题,这是因为我们的DDBB服务器具有与Apache服务器不同的时间配置,并且它给我们带来了奇怪的结果。

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

答案 2 :(得分:-1)

您可以在the PHP manual中的评论中看到人们遇到麻烦,包括迭代DatePeriod时的结束日期。那里提出了各种修改可以帮助解决这个问题,但是对于你正在做的事情,你并不需要结束日期,因为你总是只是从当前日期返回一定天数。

您可以使用the DatePeriod constructor的“重复”表单来包含结束日期。

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);