我使用这个代码,并能正常工作至今:
<?php
$start = (new DateTime('2019-02-11'));
$end = (new DateTime('2019-04-23'));
$months = new DatePeriod($start, DateInterval::createFromDateString('1 month'), $end);
$days = new DatePeriod($start, DateInterval::createFromDateString('1 day'), $end);
echo "<table border=1><tr>";
foreach ($months as $month){
echo "<td>".$month->format("M");
foreach ($days as $day)
{
if($month->format("M")==$day->format("M")){$d++;}
}
echo " (".$d." days)</td>";
unset($d);
}
echo "</tr></table>";
?>
输出是:
月(18天)月(31天)月(22天)
不幸的是,“forgots”四月之以某种方式的最后一天(必须是23天像$到底说明)。
为什么代码不算/包括的最后一天?
我是否需要像“加1日”添加到$结束日期?
感谢大伙们!
您的结束日期时间戳00:00:00这意味着,根据DateTime
间隔对象,天还没有实际尚未开始。如果你改变你的$end
到$end = (new DateTime('2019-04-23 01:00:00'));
它将包括这一天为好。
此外,你应该很可能在你的foreach循环添加$d = 0;
几个月。现在你没有定义它。 (默认是0,所以它仍然有效,但最好还是自己定义。)
我有Dirks answer不同意。使用\DateTime
每天从零开始(00:00:00
)。
可测试用:
<?php
$start = new \DateTimeImmutable('2019-02-10 23:59:57');
for ($i = 0; $i < 7; ++$i) {
echo $start->format('c'), "\n";
$start = $start->modify('+1 second');
}
这说明(我的时区):
2019-02-10T23:59:57+01:00
2019-02-10T23:59:58+01:00
2019-02-10T23:59:59+01:00
2019-02-11T00:00:00+01:00
2019-02-11T00:00:01+01:00
2019-02-11T00:00:02+01:00
2019-02-11T00:00:03+01:00
与您的代码的问题,是\DatePeriod
排除结束日期。并且这样的内循环,每天运行短。
<?php
$start = new \DateTimeImmutable('2019-02-11');
$end = $start->modify('+3 days');
$period = new \DatePeriod($start, new \DateInterval('P1D'), $end);
foreach ($period as $date) {
echo $date->format('c'), "\n";
}
echo 'actual end date: ', $end->format('c');
# 2019-02-11T00:00:00+01:00
# 2019-02-12T00:00:00+01:00
# 2019-02-13T00:00:00+01:00
# actual end date: 2019-02-14T00:00:00+01:00
但整体的做法是有点过分。例如,下面给出与(IMO)更好的语义和只有最小循环的相同的结果:
<?php
/**
* @param DateTimeImmutable $start
* @param DateTimeImmutable $end
*
* @return Generator
*/
function remainingDaysPerMonthBetween(\DateTimeImmutable $start, \DateTimeImmutable $end): \Generator {
while ($start < $end) {
$diff = $start->diff(min(
$start->modify('last day of this month'),
$end
));
yield [$start, $diff->days];
$start = $start->modify('first day of next month');
}
}
$start = new \DateTimeImmutable('2019-02-11');
$end = new \DateTimeImmutable('2019-04-23');
foreach (remainingDaysPerMonthBetween($start, $end) as [$date, $remainingDays]) {
printf("%s: %d\n", $date->format('M'), $remainingDays + 1);
}