【问题标题】:Array of time periods with start and end date by range具有按范围的开始和结束日期的时间段数组
【发布时间】:2019-07-13 15:07:23
【问题描述】:

我想生成一个表,其中包含基于时间间隔数组的值,该数组显示每个时期的开始和结束日期。周期可以是固定间隔,例如(P1D、P1M 等)。

我已经有一个生成关闭(过去)期间的函数,但我找不到使用未来日期的方法。

这是函数:

function interval($start, $interval, $break = 0)
{
    $result = array();

    $today = date("Y-m-d");
    if ($break == 0) {
        if ($today < $start) $break = 1;
    }

    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));

    $x = TRUE;
    if ($break == 0) {
        do {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array(
                'begin' => $f1,
                'end'    => $f2
            );
            $x = ($f1 <= $today && $f2 >= $today) ? TRUE : FALSE;
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

        } while (!$x);

    } else {

        for ($n = 1; $n <= $break; $n++) {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array(
                'begin' => $f1,
                'end'    => $f2
            );
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));
        }
    }
    return $result;
}

只需调用函数即可:

print_r(interval('2019-01-01', 'P1M'));

结果如下:

(
    [0] => Array
        (
            [begin] => 2019-01-01
            [end] => 2019-02-01
        )

    [1] => Array
        (
            [begin] => 2019-02-02
            [end] => 2019-03-01
        )

)

我希望在未来期间也这样做,例如,从 2019 年 1 月 1 日到 2023 年 1 月 1 日,间隔 1 个月 (P1M)。

更新

@dWinder 的答案是我寻找的解决方案最接近的东西,而无需及时旅行 =),它在每月和每年的间隔中都非常有效,但周期较短(P15D、P1W、P1D),该脚本提出了我无法识别的问题。

我更新了您发布的函数,使其正确地通过数组并保持如下:

function interval($start, $interval, $maxPeriods = 100, $end = NULL) {
    $result = array();
    //$today = date("Y-m-d"); ** Variable not used, disable it **
    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));
    do {
        $date->add($interval);
        $f2 = $date->format('Y-m-d');
        $result[] = array( 'begin' => $f1, 'end' => $f2);
        if ($end <> NULL && $end == $f2) break; // if over the end date stop the loop
        $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

    } while (++$maxPeriods); // I changed -- to ++ to avoid stopping the loop
    return $result;
}

更新后的函数是这样使用的:

print_r(interval('2019-01-01', 'P1M', NULL, '2023-01-01'));

结果:

(
    [0] => Array
        (
            [begin] => 2019-01-01
            [end] => 2019-02-01
        )

    [1] => Array
        (
            [begin] => 2019-02-02
            [end] => 2019-03-01
        )

    [2] => Array
        (
            [begin] => 2019-03-02
            [end] => 2019-04-01
        )

    [3] => Array
        (
            [begin] => 2019-04-02
            [end] => 2019-05-01
        )

    [4] => Array
        (
            [begin] => 2019-05-02
            [end] => 2019-06-01
        )

    [5] => Array
        (
            [begin] => 2019-06-02
            [end] => 2019-07-01
        )

    [6] => Array
        (
            [begin] => 2019-07-02
            [end] => 2019-08-01
        )

    [7] => Array
        (
            [begin] => 2019-08-02
            [end] => 2019-09-01
        )

    [8] => Array
        (
            [begin] => 2019-09-02
            [end] => 2019-10-01
        )

    [9] => Array
        (
            [begin] => 2019-10-02
            [end] => 2019-11-01
        )

    [10] => Array
        (
            [begin] => 2019-11-02
            [end] => 2019-12-01
        )

    [11] => Array
        (
            [begin] => 2019-12-02
            [end] => 2020-01-01
        )
)...

【问题讨论】:

  • 我的帖子对您​​有帮助吗?
  • @dWinder 您的回答是最接近我正在寻找的解决方案的东西,谢谢!
  • 为什么将if ($end &lt;&gt; NULL &amp;&amp; $end &lt; $f2) break; 行中的“while (++$maxPeriods); 那么最大值将不起作用 - 你想达到什么目的?更重要的是 - 更短的周期有什么问题?
  • @dWinder 我将“
  • 我猜 P1W 和 P15D 在使用 == 时将是无限循环,因为它可能会跳过确切的结束日期 - 我建议使用 &lt; 并在函数之后删除最后一个元素

标签: php arrays datetime codeigniter-3


【解决方案1】:

更好的解决方案是发送“end”参数并检查它(除了“maxPeriods”

考虑如下(注意代码中的注释):

function interval($start, $interval, $maxPeriods = 100, $end = null) {
    $result = array();
    $today = date("Y-m-d");
    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));
    do {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array( 'begin' => $f1, 'end' => $f2);
            if ($end && $end < $f2) break; // if over the end date stop the loop
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

    } while (--$maxPeriods); //till you get max elements
    return $result;
}

现在用

调用它
print_r(interval('2019-01-01', 'P1M', 48));
//or
print_r(interval('2019-01-01', 'P1M', null, "2023-01-01"));

注意第一个角色遇到了中断循环(结束日期或最大元素)

【讨论】:

    【解决方案2】:

    时间机器会有所帮助 :) 如果程序正确计算过去的时期,那么如果它今天“认为”是 '2023-01-01'(给予或接受),它会正确计算过去的时期。可以添加$end 参数,默认为今天吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      • 2020-11-19
      • 1970-01-01
      相关资源
      最近更新 更多