获取给定DateTime的下一个,如果日期不同,则跳过

问题描述 投票:4回答:2

我希望从给定的日期和时间获得下个月的日期和时间。这是我现在拥有的:

$dt = new DateTime('2019-01-31');

for ($i=0; $i < 10; $i++) {
    $dt->add(new DateInterval('P1M'));
    $final = $dt->format('Y-m-d');
    echo $final."\n";
}

// Output:
// 2019-03-03
// 2019-04-03
// 2019-05-03
// 2019-06-03
// 2019-07-03

问题是,它将日期从“31”更改为“02”,因为在2月份,没有第31天。所以在没有例如30或31的月份中,我想跳过那些月但是保持那些日子一样。

所以这里应该是预期的输出:

// 2019-03-31
// 2019-05-31
// 2019-07-31
// 2019-08-31
// 2019-10-31

我怎样才能做到这一点?

php date datetime time
2个回答
3
投票

可靠地执行此操作的一种方法是继续向开始日期添加更多月份,而不是不断添加一个月。然后,您可以将新日期的日期与开始日期的日期进行比较,如果它们相同,则回显结果:

$dt = new DateTime('2019-01-31');
$day = $dt->format('d');
for ($i=1; $i <= 10; $i++) {
    $next = clone $dt;
    $next->add(new DateInterval("P{$i}M"));
    if ($next->format('d') != $day) continue;
    echo $next->format('Y-m-d') ."\n";
}

输出:

2019-03-31
2019-05-31 
2019-07-31 
2019-08-31 
2019-10-31

Demo on 3v4l.org

更新

如果要从开始输出10个月(满足日期条件),则可以使用此代码计算输出数量:

$dt = new DateTime('2019-01-31');
$day = $dt->format('d');
$months = 0;
for ($i=1; $months < 10; $i++) {
    $next = clone $dt;
    $next->add(new DateInterval("P{$i}M"));
    if ($next->format('d') != $day) continue;
    echo $next->format('Y-m-d') ."\n";
    $months++;
}

输出:

2019-03-31 
2019-05-31 
2019-07-31 
2019-08-31 
2019-10-31 
2019-12-31
2020-01-31 
2020-03-31
2020-05-31 
2020-07-31

Demo on 3v4l.org


3
投票

这有点棘手,因为你的DateTime()对象不断变化。但基本上你需要:

  1. 跟踪每月的哪一天
  2. 修改日期,使其到达本月的第一天,这样您就不会跳过任何月份
  3. 加一个月
  4. 检查月份的长度,如果它太短,请跳过它
  5. 格式化您的日期,放回正确的一天。

.

<?php
$dt = new DateTime('2019-01-31');
$day = $dt->format('d');
for ($i=0; $i < 10; $i++) {
    $dt->modify('first day of this month')->add(new DateInterval('P1M'));
    if ($dt->format('t') < $day) {
        continue;
    }
    $final = $dt->format('Y-m-' . $day);
    echo $final."\n";
}

产量

2019-03-31
2019-05-31
2019-07-31
2019-08-31
2019-10-31

Demo

这是一个显示10个结果的示例。通过循环有很多方法可以做到这一点。我选择了一个do / while循环,因为我认为它们没有得到足够的使用。 :)

<?php

$dt = new DateTime('2019-01-31');
$day = $dt->format('d');
$i = 0;
do {
    $dt->modify('first day of this month')->add(new DateInterval('P1M'));
    if ($dt->format('t') < $day) {
        continue;
    }
    $final = $dt->format('Y-m-' . $day);
    echo $final."\n";
    $i++;
} while ($i < 10);

Demo

© www.soinside.com 2019 - 2024. All rights reserved.