如何循环已经过去的月份

时间:2015-03-17 11:05:58

标签: php

我有以下内容循环浏览一年中的每个月。但是,它似乎跳过二月。

$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 months http://php.net/manual/en/datetime.add.php

3 个答案:

答案 0 :(得分:3)

为什么不使用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

答案 1 :(得分:0)

这是因为二月有28天而你的间隔是一个月(30天)。所以它从1月30日到3月2日跳过了30天。然后它移动到三月的最后一天。

更改

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

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

答案 2 :(得分:-1)

您的第一次约会是2015年1月31日。自2月份没有第31届以来​​,它将持续到3月3日。然后你告诉它到那个月末,这就是为什么你要在1月而不是2月之后到达3月底。