获取最近12个月的PHP


Get the last 12 months in PHP

这是我今天学到的一个有趣的问题

我需要用过去12个月的数据填充一个数组,从过去一个月开始。所以在2011年8月,最后12个月将是2010年9月到2011年7月。为此,我使用:

for ($i = 1; $i <= 12; $i++)
    $months[] = date("Y-m%", strtotime("-$i months"));

上面的代码在8月30日运行正常。我得到最近12个月:

array
    0 => string '2011-07%' (length=8)
    1 => string '2011-06%' (length=8)
    2 => string '2011-05%' (length=8)
    3 => string '2011-04%' (length=8)
    4 => string '2011-03%' (length=8)
    5 => string '2011-02%' (length=8)
    6 => string '2011-01%' (length=8)
    7 => string '2010-12%' (length=8)
    8 => string '2010-11%' (length=8)
    9 => string '2010-10%' (length=8)
    10 => string '2010-09%' (length=8)
    11 => string '2010-08%' (length=8)

但是当我在8月31日运行这个时,我得到:

array
    0 => string '2011-07%' (length=8)
    1 => string '2011-07%' (length=8)
    2 => string '2011-05%' (length=8)
    3 => string '2011-05%' (length=8)
    4 => string '2011-03%' (length=8)
    5 => string '2011-03%' (length=8)
    6 => string '2011-01%' (length=8)
    7 => string '2010-12%' (length=8)
    8 => string '2010-12%' (length=8)
    9 => string '2010-10%' (length=8)
    10 => string '2010-10%' (length=8)
    11 => string '2010-08%' (length=8)

我试过Windows和Unix。有人能解决这个问题吗?

我相信有人有更优雅的解决方案,但你可以从本月1日开始倒数。

for ($i = 1; $i <= 12; $i++) {
    $months[] = date("Y-m%", strtotime( date( 'Y-m-01' )." -$i months"));
}

这是因为不是每个月都有31号。所以strtotime()提前到下个月。即4/31 = 5/1。

你最好使用mktime(),因为它是数字strtotime()

更新

为了利用像strtotime()这样的智能功能,避免跟踪mktime()的年份,我的建议如下:

$month = time();
for ($i = 1; $i <= 12; $i++) {
  $month = strtotime('last month', $month);
  $months[] = date("r", $month);
}
print_r($months);

我想提出一个使用DatePeriod代替的替代解决方案。

这里有一些需要注意的警告。首先,您不希望像时区信息或/时间信息这样的东西妨碍您。你只对月份感兴趣。因此,我们可以将这些信息规范化,以防止诸如溢出和夏令时并发症等并发症。因为只有在这些罕见事件发生的特定日期/时间,您才能容易陷入此陷阱。

$start = new DateTime;
$start->setDate($start->format('Y'), $start->format('n'), 1); // Normalize the day to 1
$start->setTime(0, 0, 0); // Normalize time to midnight
$start->sub(new DateInterval('P12M'));
$interval = new DateInterval('P1M');
$recurrences = 12;
foreach (new DatePeriod($start, $interval, $recurrences, true) as $date) {
    echo $date->format('F, Y'), "'n"; // attempting to make it more clear to read here
}
输出:

<>之前2019年2月2019年3月2019年4月2019年5月2019年6月2019年7月2019年8月2019年9月2019年10月2019年11月2019年12月2020年1月

我认为这将工作:

$this_month = date("n", time());
$this_year = date("Y", time());
$months_array = array();
for ($i = $this_month - 1; $i > ($this_month - 13); $i--) {
    echo "$i<br>";
    if ($i < 1) {
        $correct_month_number = $i + 12;
        $months_array[] = array($correct_month_number, $this_year - 1);
    }
    else {
        $months_array[] = array($i, $this_year);
    }
}
echo "<pre>"; var_dump($months_array); echo "</pre>";

数据类型有点松散,但这可以完成工作。这样做的好处是,它只针对当前月份和年份调用date()函数一次。剩下的逻辑就是简单的数学。不用担心每个月的长度。

然后你可以使用$months_array数组来构建你需要的任何东西

不同月份长度的乐趣。strtotime是字面上的意思,把"8月31日"变成"9月31日",这是不存在的。最后是10月1日之类的。更安全的方法是:

for ($i = 1; $i <= 12; $i++) {
    $months[] = date("Y-m%", mktime(0, 0, 0, $i, 1, 2011));
}

strtotime有时很神奇,但它不可靠,当然也不"快"。