我想使用PHP DateInterval迭代几个月:
$from = new DateTime();
$from->setDate(2014, 1, 31);
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
我预计它会在2月28日1月31日返回(因为DateInterval是1个月),但实际上它将于4月31日,3月3日,4月3日返回...因此跳过2月。
有没有办法简单地做到这一点?
谢谢!
编辑:作为参考,这里有一个似乎涵盖大多数用例的解决方案:
$date = new DateTime('2014-01-31');
$start = $date->format('n');
for ($i = 0; $i < 28; $i++) {
$current = clone $date;
$current->modify('+'.$i.' month');
if ($current->format('n') > ($start % 12) && $start !== 12) {
$current->modify('last day of last month');
}
$start++;
echo $current->format('Y-m-d').PHP_EOL;
}
答案 0 :(得分:3)
您可以使用DateTime::modify()
:
$date = new DateTime('last day of january');
echo $date->format('Y-m-d').PHP_EOL;
for ($i = 1; $i < 12; $i++) {
$date->modify('last day of next month');
echo $date->format('Y-m-d').PHP_EOL;
}
编辑:我想我不明白你的问题。这是一个新版本:
$date = new DateTime('2014-01-31');
for ($i = 0; $i < 12; $i++) {
$current = clone $date;
$current->modify('+'.$i.' month');
if ($current->format('n') > $i + 1) {
$current->modify('last day of last month');
}
echo $current->format('Y-m-d').PHP_EOL;
}
答案 1 :(得分:0)
您可以尝试这样:
$date = new DateTime();
$lastDayOfMonth = $date->modify(
sprintf('+%d days', $date->format('t') - $date->format('j'))
);
答案 2 :(得分:0)
我会这样做
$max = array (
31,28,31,30,31,30,31,31,30,31,30,31
); //days in month
$month = 1;
$year = 2014;
$day = 31;
$iterate = 12;
$dates = array();
for ($i = 0;$i < $iterate;$i++) {
$tmp_month = ($month + $i) % 12;
$tmp_year = $year + floor($month+$i)/12;
$tmp_day = min($day, $max[$tmp_month]);
$tmp = new DateTime();
$tmp->setDate($tmp_year, $tmp_month + 1, $tmp_day);
$dates[] = $tmp;
}
var_dump($dates);
如果可能的话,这会保持每个月的同一天
答案 3 :(得分:0)
问题是由该范围内每个月的最后一天之间的差异引起的。即。 2月以28
代替31
结束,并且从最后一天2014-01-31 + 1 month = 2014-03-03
https://3v4l.org/Y42QJ
要解决DatePeriod
的问题并将其简化一点,请使用first day of this month
,通过将指定的日期重置为指定月份的第一天来调整初始日期。
然后,在迭代过程中,您可以使用last day of this month
来检索当前迭代月份的界限,从而修改日期期限日期。
$from = new DateTime('2014-01-31');
$from->modify('first day of this month'); //2014-01-01
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
foreach ($period as $date) {
echo $date->modify('last day of this month')->format('Y-m-d');
}
结果:
2014-01-31
2014-02-28
2014-03-31
2014-04-30
2014-05-31
2014-06-30
2014-07-31
2014-08-31
2014-09-30
2014-10-31
2014-11-30
2014-12-31
2015-01-31
然后在此方法上进行扩展,以便从指定的日期检索所需的日期,例如29th
。您可以提取指定的日期,并在该日期超出该月份的范围时根据需要调整当前迭代的月份。
$from = new DateTime('2014-01-29');
$day = $from->format('j');
$from->modify('first day of this month'); //2014-01-01
$period = new DatePeriod($from, new DateInterval('P1M'), 12);
foreach ($period as $date) {
$lastDay = clone $date;
$lastDay->modify('last day of this month');
$date->setDate($date->format('Y'), $date->format('n'), $day);
if ($date > $lastDay) {
$date = $lastDay;
}
echo $date->format('Y-m-d');
}
结果:
2014-01-29
2014-02-28 #notice the last day of february is used
2014-03-29
2014-04-29
2014-05-29
2014-06-29
2014-07-29
2014-08-29
2014-09-29
2014-10-29
2014-11-29
2014-12-29
2015-01-29