获取给定日期时间的下一个时间,并跳过不同日期的情况。

4

我想从给定的日期和时间获取下个月的日期和时间。这是我现在的代码:

$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”,因为二月份没有31号。因此,在那些没有30或31天的月份,我想跳过这些月份但保持相同的日期。
以下是期望输出结果:
// 2019-03-31
// 2019-05-31
// 2019-07-31
// 2019-08-31
// 2019-10-31

我怎样才能做到这一点?

一个非常良好格式化的SO问题,立即进入重点并展示自己的方法、输出和预期结果。我希望所有贡献者都能像这样做。+1 - Pinke Helga
@Quasimodo的克隆体 哈哈谢谢!我发完这个问题后有点意识到了 :P - baileyJchoi
2个回答

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

演示

这是一个显示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


当你的回答如此相似,我怎么能不点赞呢? :-) - Nick
@Nick Both +1,因为这可能是PHP中最短的形式。然而,更重要的是,应该给这位相对较新的OP点赞,因为他清楚地阐述了自己的方法,输出和预期结果。 - Pinke Helga
太棒了,各位!但是当它到达年底时,它怎么能回到一月呢?由于for循环中的i = 10,它应该显示10个结果。 - baileyJchoi
我更新了我的答案以显示10个结果。两个答案都同样有效,只是个人偏好的问题。希望它们能够演示在PHP中可以用多种方式完成任务。 - John Conde
是的,非常感谢!我接受了Nick的答案,因为它基本上就是我想要的,但是因为这种独特的方法而+1! - baileyJchoi

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

在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

在 3v4l.org 上的演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接