我正在使用此代码,到目前为止效果良好:
$event->Creator['email'] should also work.
输出为:
2月(18天)3月(31天)4月(22天)
不幸的是,它以某种方式“忘记”了4月的最后一天(必须像$ end中所述的那样是23天)。
为什么代码不计算/包括最后一天?
我需要在结束日期前添加“加1天”之类的内容吗?
谢谢你们!
答案 0 :(得分:0)
您的结束日期具有时间戳00:00:00,这意味着根据DateTime
间隔对象,该日期实际上尚未真正开始。如果您将$end
更改为$end = (new DateTime('2019-04-23 01:00:00'));
,则该日期也将包括在内。
另外,您可能应该在几个月的foreach循环中添加$d = 0;
。现在您还没有定义它。 (默认将其设置为0,因此它仍然可以使用。但是最好自己定义。)
答案 1 :(得分: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);
}