如何在已经过去的几个月里循环


How to loop through months that have been already passed

一年中的每个月我都要循环使用以下内容。然而,它似乎跳过了二月。

$start = new DateTime('2015-01-01');
$start->modify('last day of this month');
$current = new DateTime('now');
$end = new DateTime('2018-01-01');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
$timestamps = array();
foreach ($period as $dt) {
    $dt->modify('last day of this month');
    echo 'C:' . $current->format('d F Y') . '<br>';
    echo 'S:' . $start->format('d F Y') . '<br>';
    echo 'D:' . $dt->format('d F Y') . '<br>';
    echo '<br><br>';
}

然而,上述输出:

C:17 March 2015
S:31 January 2015
D:31 January 2015
C: 17 March 2015
S:31 January 2015
D:31 March 2015
C: 17 March 2015
S:31 January 2015
D:30 April 2015

有人能认出我的错误吗?我期望第二个D具有28 February 2015的值。

我只想要一份已经过去的月份的清单。

更新

MLeFevre在评论中强调的问题是,使用日期间隔可能很棘手。参见Example #3 Beware when adding monthshttp://php.net/manual/en/datetime.add.php.

与其使用DatePeriod,为什么不使用modify方法呢

$current = new DateTime('now');
$end = new DateTime('2018-01-01');
while($current < $end) {
    $current->modify('last day of next month');
    echo 'C:' . $current->format('d F Y') . '<br>';
}

在你的问题中,你首先要加一个月,然后到那个月底。这是行不通的,因为每个月的时间长短各不相同。

样本输出:

C:30 April 2015
C:31 May 2015
C:30 June 2015
C:31 July 2015
C:31 August 2015
C:30 September 2015
C:31 October 2015
C:30 November 2015
C:31 December 2015
C:31 January 2016
C:29 February 2016
C:31 March 2016
// etc.

要从$start循环到$current,您可以稍微更改如下逻辑:

$start = new DateTime('2015-01-31'); // start from end of month
$current = new DateTime('now');
do {
    echo 'C:' . $start->format('d F Y') . '<br>';    
} while($start->modify('last day of next month') < $current);

输出:

C:31 January 2015
C:28 February 2015

发生这种情况是因为二月有28天,而您的间隔时间是1个月(30天)。因此,它从1月30日到3月2日跳过了30天。然后它移动到三月的最后一天。

更改

$start->modify('last day of this month');

$start->modify('first day of this month');

您的第一次约会是2015年1月31日。由于2月没有31日,所以它将持续到3月3日。然后你告诉它到那个月底,这就是为什么你在1月之后到3月底,而不是2月。