【问题标题】:Get next of given DateTime and skip if day is not the same获取给定日期时间的下一个,如果日期不同则跳过
【发布时间】:2019-02-27 01:32:24
【问题描述】:

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

$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

我该怎么做?

【问题讨论】:

  • 一个非常好的格式和格式的 SO 问题,立即切入主题,并展示了自己的方法、输出和预期结果。我希望所有贡献者都这样做。 +1
  • @Quasimodo'sclone 哈哈谢谢!在我发布问题后我有点意识到这一点:P

标签: php date datetime time


【解决方案1】:

可靠地做到这一点的一种方法是不断增加开始日期的月份,而不是不断增加一个月。然后你可以将新日期的日期与开始日期的日期进行比较,如果它们相同,则回显结果:

$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

【讨论】:

    【解决方案2】:

    这有点棘手,因为您的 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

    【讨论】:

    • 当他们如此相似时,我怎么能不赞成你的答案? :-)
    • @Nick Both +1 可能是 PHP 中最短的形式。然而,更重要的是,相对较新的 OP 应该得到支持,因为它清楚地表达了自己的方法、输出和预期的结果。
    • 很好的答案伙计们!但是一到年底,怎么能回到一月份呢?由于 for 循环 i = 10,它应该显示 10 个结果。
    • 我更新了我的答案以显示 10 个结果。两个答案都同样有效,只是一个偏好问题。希望它们能帮助您展示如何在 PHP 中以不止一种方式做事。
    • 是的,非常感谢!我接受了尼克的回答,因为这几乎是我要去的地方,但是对于这种独特的方法 +1!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    相关资源
    最近更新 更多