数天“忘记”最后一天

时间:2019-02-11 10:15:12

标签: php date

我正在使用此代码,到目前为止效果良好:

$event->Creator['email'] should also work.

输出为:

2月(18天)3月(31天)4月(22天)

不幸的是,它以某种方式“忘记”了4月的最后一天(必须像$ end中所述的那样是23天)。

为什么代码不计算/包括最后一天?

我需要在结束日期前添加“加1天”之类的内容吗?

谢谢你们!

2 个答案:

答案 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

https://3v4l.org/8Q3kb


您的代码存在问题,因为\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);
}

https://3v4l.org/BCAYq